From 96701613c87e30a2436f5b56caaf8bd1c2997412 Mon Sep 17 00:00:00 2001 From: ipatini Date: Mon, 8 Jan 2024 18:59:31 +0200 Subject: [PATCH] Updated monitoring with the latest developments * Moved 'ems-core' into 'nebulous' dir, and updated it from main repo. * Add 'ems-nebulous' plugin code, the 'metric-model' specs, and a top-level pom.xml to build everything (including EMS-Nebulous image) * Added .gitattributes and changed EOL to LF in top-level files. * Also adopting code to pass Zuul checks Change-Id: Ic414a1fa382d0a9112cbc805375cf603af59cd37 --- .gitattributes | 1 + .gitignore | 17 +- charts/nebulous-monitoring/values.yaml | 2 +- .../main/resources/META-INF/spring.factories | 1 - .../src/main/resources/banner-alternative.txt | 7 - .../translator/src/main/resources/banner.txt | 8 - .../src/main/resources/rule-templates.yml | 237 ----- nebulous/Dockerfile | 16 + .../ems-core}/.gitattributes | 0 {ems-core => nebulous/ems-core}/.gitignore | 0 .../ems-core}/README-for-TESTING.md | 0 .../ems-core}/baguette-client-install/pom.xml | 0 .../install/ClientInstallationProperties.java | 2 + .../ClientInstallationRequestListener.java | 247 ++++- .../install/ClientInstallationTask.java | 3 +- .../client/install/ClientInstaller.java | 85 +- .../client/install/ClientInstallerPlugin.java | 0 .../InstallationContextProcessorPlugin.java | 0 .../client/install/SshClientInstaller.java | 10 +- .../baguette/client/install/SshConfig.java | 0 .../client/install/SshJsClientInstaller.java | 3 +- .../baguette/client/install/StreamLogger.java | 0 .../client/install/api/INodeRegistration.java | 4 + .../helper/AbstractInstallationHelper.java | 3 +- .../install/helper/InstallationHelper.java | 1 + .../helper/InstallationHelperFactory.java | 0 .../install/helper/VmInstallationHelper.java | 11 +- .../instruction/AbstractInstructionsBase.java | 0 .../instruction/INSTRUCTION_RESULT.java | 0 .../install/instruction/INSTRUCTION_TYPE.java | 0 .../install/instruction/Instruction.java | 2 +- .../instruction/InstructionsService.java | 4 +- .../install/instruction/InstructionsSet.java | 0 .../plugin/AllowedTopicsProcessorPlugin.java | 13 +- .../plugin/PrometheusProcessorPlugin.java | 3 +- .../selfhealing/ClientRecoveryPlugin.java | 0 .../selfhealing/SelfHealingManagerImpl.java | 0 .../ServerSelfHealingProperties.java | 0 .../ems-core}/baguette-client/LICENSE | 0 .../baguette-client/bin/baguette-client | 0 .../ems-core}/baguette-client/bin/client.sh | 0 .../ems-core}/baguette-client/bin/install.sh | 0 .../ems-core}/baguette-client/bin/kill.sh | 0 .../ems-core}/baguette-client/bin/run.bat | 0 .../ems-core}/baguette-client/bin/run.sh | 0 .../conf/baguette-client.properties.sample | 0 .../baguette-client/conf/baguette-client.yml | 0 .../baguette-client/conf/baguette.json | 0 .../baguette-client/conf/logback-spring.xml | 0 .../baguette-client/conf/netdata.json | 0 .../ems-core}/baguette-client/logs/output.txt | 0 .../ems-core}/baguette-client/pom.xml | 0 .../baguette-client-installation-package.xml | 0 .../ems/baguette/client/BaguetteClient.java | 0 .../baguette/client/BaguetteClientCLI.java | 0 .../client/BaguetteClientProperties.java | 0 .../imu/ems/baguette/client/Collector.java | 0 .../ems/baguette/client/CommandExecutor.java | 25 + .../gr/iccs/imu/ems/baguette/client/Sshc.java | 0 .../client/cluster/AbstractLogBase.java | 0 .../baguette/client/cluster/BrokerUtil.java | 0 .../baguette/client/cluster/ClusterCLI.java | 0 .../client/cluster/ClusterManager.java | 0 .../cluster/ClusterManagerProperties.java | 0 .../baguette/client/cluster/ClusterTest.java | 0 .../client/cluster/MemberScoreFunction.java | 0 .../client/cluster/MemberWithScore.java | 0 .../baguette/client/cluster/TestCallback.java | 2 +- .../collector/ClientCollectorContext.java | 0 .../collector/netdata/NetdataCollector.java | 15 +- .../prometheus/PrometheusCollector.java | 15 +- .../plugin/recovery/NodeInfoHelper.java | 0 .../plugin/recovery/SelfHealingPlugin.java | 6 +- .../main/resources/META-INF/spring.factories | 0 .../src/main/resources/banner-1.txt | 0 .../src/main/resources/banner.txt | 0 .../ems-core}/baguette-server/pom.xml | 9 +- .../ems/baguette/server/BaguetteServer.java | 2 +- .../baguette/server/ClientShellCommand.java | 9 +- .../server/GroupingConfigurationHelper.java | 0 .../imu/ems/baguette/server/NodeRegistry.java | 0 .../baguette/server/NodeRegistryEntry.java | 6 +- .../baguette/server/ServerCoordinator.java | 0 .../gr/iccs/imu/ems/baguette/server/Sshd.java | 2 +- .../server/coordinator/NoopCoordinator.java | 10 +- .../coordinator/ServerCoordinatorTimeWin.java | 4 +- .../coordinator/ServerCoordinatorWaitAll.java | 0 .../server/coordinator/TestCoordinator.java | 0 .../coordinator/TwoLevelCoordinator.java | 0 .../AtLeastTwoZoneManagementStrategy.java | 0 .../cluster/ClusterSelfHealing.java | 0 .../coordinator/cluster/ClusterZone.java | 2 +- .../cluster/ClusterZoneDetector.java | 0 .../cluster/ClusteringCoordinator.java | 6 +- .../DefaultZoneManagementStrategy.java | 0 .../coordinator/cluster/IClusterZone.java | 0 .../cluster/IClusterZoneDetector.java | 0 .../cluster/IZoneManagementStrategy.java | 0 .../properties/BaguetteServerProperties.java | 4 +- {ems-core => nebulous/ems-core}/bin/client.sh | 0 .../ems-core}/bin/cp2cdo.bat | 0 {ems-core => nebulous/ems-core}/bin/cp2cdo.sh | 0 {ems-core => nebulous/ems-core}/bin/detect.sh | 0 .../bin/initialize-MELODIC-keystores.sh | 0 .../ems-core}/bin/initialize-keystores.bat | 0 .../ems-core}/bin/initialize-keystores.sh | 0 .../ems-core}/bin/jwtutil.bat | 2 +- .../ems-core}/bin/jwtutil.sh | 2 +- {ems-core => nebulous/ems-core}/bin/run.bat | 2 +- {ems-core => nebulous/ems-core}/bin/run.sh | 2 +- {ems-core => nebulous/ems-core}/bin/sysmon.sh | 0 .../ems-core}/bin/update-credentials.sh | 0 .../ems-core}/broker-cep/client.bat | 0 .../ems-core}/broker-cep/pom.xml | 5 +- .../imu/ems/brokercep/BrokerCepConsumer.java | 2 +- .../imu/ems/brokercep/BrokerCepService.java | 8 +- .../BrokerCepStatementSubscriber.java | 2 +- .../gr/iccs/imu/ems/brokercep/EventCache.java | 0 .../imu/ems/brokercep/EventForwarder.java | 0 .../broker/BrokerAdvisoryWatcher.java | 8 +- .../ems/brokercep/broker/BrokerConfig.java | 2 +- .../brokercep/broker/InterceptorHelper.java | 0 .../SimpleBrokerAuthorizationPlugin.java | 0 .../AbstractMessageInterceptor.java | 0 .../interceptor/CompositeInterceptor.java | 0 .../LogMessageUpdateInterceptor.java | 4 +- .../MessageForwarderInterceptor.java | 2 +- ...odePropertiesMessageUpdateInterceptor.java | 0 .../SequentialCompositeInterceptor.java | 0 ...SourceAddressMessageUpdateInterceptor.java | 0 .../ems/brokercep/cep/CepEvalAggregator.java | 14 +- .../cep/CepEvalAggregatorFactory.java | 0 .../ems/brokercep/cep/CepEvalFunction.java | 18 +- .../imu/ems/brokercep/cep/CepExtensions.java | 2 - .../imu/ems/brokercep/cep/CepService.java | 0 .../iccs/imu/ems/brokercep/cep/MathUtil.java | 15 +- .../brokercep/cep/StatementSubscriber.java | 0 .../imu/ems/brokercep/event/EventMap.java | 16 +- .../ems/brokercep/event/EventRecorder.java | 20 +- .../properties/BrokerCepProperties.java | 0 .../brokercep/properties/NodeProperties.java | 0 .../ems-core}/broker-client/client.bat | 0 .../ems-core}/broker-client/client.sh | 0 .../ems-core}/broker-client/pom.xml | 5 +- .../imu/ems/brokerclient/BrokerClient.java | 14 +- .../imu/ems/brokerclient/BrokerClientApp.java | 41 +- .../brokerclient/event/EventGenerator.java | 2 +- .../imu/ems/brokerclient/event/EventMap.java | 0 .../properties/BrokerClientProperties.java | 0 .../src/main/resources/logback.xml | 0 .../ems-core}/common/pom.xml | 0 .../iccs/imu/ems/common/client/SshClient.java | 0 .../common/client/SshClientProperties.java | 0 .../collector/AbstractEndpointCollector.java | 98 +- .../AbstractEndpointCollectorProperties.java | 0 .../common/collector/CollectorContext.java | 0 .../collector/netdata/NetdataCollector.java | 0 .../netdata/NetdataCollectorProperties.java | 0 .../prometheus/OpenMetricsParser.java | 0 .../prometheus/PrometheusCollector.java | 0 .../PrometheusCollectorProperties.java | 0 .../imu/ems/common/misc/EventConstant.java | 0 .../common/misc/SystemResourceMonitor.java | 18 +- .../imu/ems/common/plugin/PluginManager.java | 0 .../common/recovery/AbstractRecoveryTask.java | 0 .../recovery/EmsClientRecoveryTask.java | 0 .../NetdataAgentLocalRecoveryTask.java | 0 .../recovery/NetdataAgentRecoveryTask.java | 0 .../ems/common/recovery/RECOVERY_COMMAND.java | 0 .../ems/common/recovery/RecoveryConstant.java | 0 .../ems/common/recovery/RecoveryContext.java | 0 .../imu/ems/common/recovery/RecoveryTask.java | 0 .../recovery/SelfHealingProperties.java | 0 .../common/recovery/ShellRecoveryTask.java | 0 .../common/recovery/VmNodeRecoveryTask.java | 0 .../selfhealing/SelfHealingManager.java | 0 ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../linux-yaml/baguette-skip.yml | 0 .../linux-yaml/baguette.yml | 0 .../linux-yaml/check-ignore.yml | 0 .../linux-yaml/detect.yml | 0 .../linux-yaml/jre.yml | 0 .../linux-yaml/netdata.yml | 0 .../linux-yaml/recover-baguette.yml | 0 .../linux-yaml/start-agents.yml | 0 .../linux-yaml/stop-agents.yml | 2 +- .../linux/baguette-remove.json | 0 .../linux/baguette-skip.json | 0 .../linux/baguette.json | 0 .../linux/check-ignore.json | 0 .../baguette-client-install/linux/detect.json | 0 .../baguette-client-install/linux/jre.json | 0 .../linux/netdata.json | 0 .../linux/recover-baguette.json | 0 .../linux/start-agents.json | 0 .../netdata/go.d/prometheus.conf | 0 .../baguette-client-install/win/win.json | 0 .../conf/baguette-client.properties.sample | 0 .../baguette-client/conf/baguette-client.yml | 0 .../baguette-client/conf/baguette.json | 0 .../baguette-client/conf/logback-spring.xml | 0 .../baguette-client/conf/netdata.json | 0 .../config-files/ems-server.properties.sample | 21 +- .../ems-core}/config-files/ems-server.yml | 21 +- .../eu.melodic.upperware.security.properties | 0 .../eu.paasage.mddb.cdo.client.properties | 0 .../logback-conf/logback-spring.xml | 0 .../ems-core}/config-files/secrets.properties | 0 .../ems-core}/control-service/pom.xml | 52 +- .../src/main/docker/Dockerfile | 44 +- .../src/main/docker/Dockerfile-alpine | 26 +- .../imu/ems/control/ApplicationContext.java | 0 .../control/ControlServiceApplication.java | 0 .../imu/ems/control/collector/Collector.java | 0 .../collector/ServerCollectorContext.java | 0 .../netdata/ServerNetdataCollector.java | 0 .../controller/BrokerCepController.java | 6 +- .../controller/ControlServiceController.java | 59 +- .../controller/ControlServiceCoordinator.java | 92 +- .../controller/ControlServiceRequestInfo.java | 0 .../controller/CredentialsController.java | 35 +- .../controller/CredentialsCoordinator.java | 0 .../controller/ManagementController.java | 57 +- .../controller/ManagementCoordinator.java | 5 + .../NodeRegistrationController.java | 66 +- .../NodeRegistrationCoordinator.java | 48 + .../controller/RestControllerException.java | 0 .../RestControllerExceptionHandler.java | 6 +- .../ems/control/info/BuildInfoProvider.java | 0 .../info/ControlServiceBuildInfoEndpoint.java | 0 .../info/ControlServiceHealthIndicator.java | 0 .../ControlServiceInfoEndpointExtension.java | 0 .../info/ControlServiceLiveInfoEndpoint.java | 0 .../ems/control/info/ControlServiceMBean.java | 0 .../control/info/ControlServiceMetrics.java | 0 .../ems/control/info/EmsInfoServiceImpl.java | 6 +- .../imu/ems/control/info/FilesController.java | 2 +- .../control/info/FilesDisabledController.java | 0 .../ems/control/info/IEmsInfoProvider.java | 0 .../imu/ems/control/info/IEmsInfoService.java | 0 .../control/info/InfoServiceController.java | 21 +- .../ems/control/info/SystemInfoProvider.java | 4 +- .../imu/ems/control/plugin/BeaconPlugin.java | 0 .../imu/ems/control/plugin/EmsInfoPlugin.java | 0 .../ems/control/plugin/MetasolverPlugin.java | 0 .../control/plugin/PostTranslationPlugin.java | 0 .../plugin/TranslationContextPlugin.java | 0 .../ems/control/plugin/WebAdminPlugin.java | 0 .../control/plugin/noop/NoopBeaconPlugin.java | 0 .../noop/NoopPostTranslationPlugin.java | 3 +- .../noop/NoopTranslationContextPlugin.java | 3 +- .../properties/ControlServiceProperties.java | 2 +- .../properties/InfoServiceProperties.java | 4 +- .../properties/StaticResourceProperties.java | 0 .../properties/TopicBeaconProperties.java | 2 +- .../properties/WebSecurityProperties.java | 9 +- .../imu/ems/control/util/EventBusCache.java | 0 .../control/util/NodeRegistrationHelper.java | 26 + .../imu/ems/control/util/TopicBeacon.java | 32 +- ...slationContextMonitorGsonDeserializer.java | 16 +- .../imu/ems/control/util/WebClientUtil.java | 0 .../control/util/jwt/JwtTokenProperties.java | 4 +- .../ems/control/util/jwt/JwtTokenService.java | 0 .../ems/control/util/jwt/JwtTokenUtil.java | 6 +- .../NoopMetricVariableValuesServiceImpl.java | 0 .../webconf/StaticResourceConfiguration.java | 0 .../imu/ems/control/webconf/WebMvcConfig.java | 0 .../control/webconf/WebSecurityConfig.java | 8 +- .../main/resources/META-INF/spring.factories | 0 .../src/main/resources/banner-0.txt | 0 .../src/main/resources/banner-1.txt | 0 .../src/main/resources/banner.txt | 0 .../src/main/resources/public/client.bat | 0 .../src/main/resources/public/client.sh | 0 .../src/main/resources/public/favicon.ico | Bin .../src/main/resources/public/index.html | 0 .../src/main/resources/version.txt | 0 {ems-core => nebulous/ems-core}/pom.xml | 32 +- .../ems-core}/translator/pom.xml | 0 .../gr/iccs/imu/ems/translate/Grouping.java | 3 + .../imu/ems/translate/NoopTranslator.java | 0 .../imu/ems/translate/TranslationContext.java | 119 ++- .../translate/TranslationContextPrinter.java | 47 +- .../TranslationContextPrinterProperties.java | 0 .../gr/iccs/imu/ems/translate/Translator.java | 0 .../translate/TranslatorApplication.java_OFF | 0 .../gr/iccs/imu/ems/translate/dag/DAG.java | 117 +-- .../iccs/imu/ems/translate/dag/DAGEdge.java | 0 .../imu/ems/translate/dag/DAGExporter.java | 214 ++++ .../iccs/imu/ems/translate/dag/DAGNode.java | 9 + .../model/AbstractInterfaceRootObject.java | 2 + .../translate/model/AbstractRootObject.java | 0 .../iccs/imu/ems/translate/model/Action.java | 2 + .../imu/ems/translate/model/Annotation.java | 2 + .../imu/ems/translate/model/Attribute.java | 2 + .../translate/model/BinaryEventPattern.java | 2 + .../model/BinaryPatternOperatorType.java | 0 .../imu/ems/translate/model/BooleanValue.java | 2 + .../model/BusyStatusMetricVariable.java | 6 +- .../model/ComparisonOperatorType.java | 7 + .../imu/ems/translate/model/Component.java | 2 + .../translate/model/CompositeConstraint.java | 2 + .../ems/translate/model/CompositeMetric.java | 2 + .../model/CompositeMetricContext.java | 2 + .../imu/ems/translate/model/Constraint.java | 2 + .../ems/translate/model/CriterionType.java | 0 .../gr/iccs/imu/ems/translate/model/Data.java | 2 + .../imu/ems/translate/model/DataSource.java | 2 + .../imu/ems/translate/model/DoubleValue.java | 2 + .../iccs/imu/ems/translate/model/Event.java | 2 + .../imu/ems/translate/model/EventPattern.java | 2 + .../iccs/imu/ems/translate/model/Feature.java | 2 + .../imu/ems/translate/model/FloatValue.java | 2 + .../imu/ems/translate/model/Function.java | 2 + .../imu/ems/translate/model/GroupingType.java | 0 .../ems/translate/model/IfThenConstraint.java | 2 + .../imu/ems/translate/model/IntValue.java | 2 + .../imu/ems/translate/model/Interval.java | 1 + .../translate/model/LogicalConstraint.java | 6 +- .../translate/model/LogicalOperatorType.java | 0 .../translate/model/MeasurableAttribute.java | 2 + .../iccs/imu/ems/translate/model/Metric.java | 2 + .../ems/translate/model/MetricConstraint.java | 2 + .../ems/translate/model/MetricContext.java | 2 + .../ems/translate/model/MetricTemplate.java | 17 +- .../ems/translate/model/MetricVariable.java | 2 + .../model/MetricVariableConstraint.java | 2 + .../iccs/imu/ems/translate/model/Monitor.java | 2 + .../imu/ems/translate/model/NamedElement.java | 2 + .../translate/model/NonFunctionalEvent.java | 2 + .../imu/ems/translate/model/NumericValue.java | 2 + .../ems/translate/model/ObjectContext.java | 2 + .../model/OptimisationRequirement.java | 2 + .../imu/ems/translate/model/PullSensor.java | 8 +- .../imu/ems/translate/model/PushSensor.java | 2 + .../imu/ems/translate/model/RawMetric.java | 2 + .../ems/translate/model/RawMetricContext.java | 2 + .../imu/ems/translate/model/Requirement.java | 2 + .../ems/translate/model/ScalabilityRule.java | 2 + .../ems/translate/model/ScalingAction.java | 2 + .../imu/ems/translate/model/Schedule.java | 7 + .../iccs/imu/ems/translate/model/Sensor.java | 14 +- .../model/ServiceLevelObjective.java | 2 + .../imu/ems/translate/model/SingleEvent.java | 2 + .../gr/iccs/imu/ems/translate/model/Sink.java | 2 + .../imu/ems/translate/model/StringValue.java | 2 + .../iccs/imu/ems/translate/model/Timer.java | 2 + .../imu/ems/translate/model/TimerType.java | 0 .../ems/translate/model/UnaryConstraint.java | 2 + .../translate/model/UnaryEventPattern.java | 2 + .../model/UnaryPatternOperatorType.java | 0 .../iccs/imu/ems/translate/model/Value.java | 2 + .../imu/ems/translate/model/ValueType.java | 0 .../imu/ems/translate/model/VariableType.java | 0 .../iccs/imu/ems/translate/model/Window.java | 2 + .../ems/translate/model/WindowCriterion.java | 2 + .../ems/translate/model/WindowProcessing.java | 2 + .../translate/model/WindowProcessingType.java | 0 .../ems/translate/model/WindowSizeType.java | 0 .../imu/ems/translate/model/WindowType.java | 0 .../mvv/MetricVariableValuesService.java | 0 {ems-core => nebulous/ems-core}/util/pom.xml | 2 +- .../imu/ems/util/ClientConfiguration.java | 0 .../gr/iccs/imu/ems/util/CredentialsMap.java | 0 .../imu/ems/util/CredentialsMapConverter.java | 0 .../gr/iccs/imu/ems/util/EmsConstant.java | 0 .../java/gr/iccs/imu/ems/util/EventBus.java | 0 .../iccs/imu/ems/util/FunctionDefinition.java | 0 .../java/gr/iccs/imu/ems/util/GROUPING.java | 0 .../imu/ems/util/GroupingConfiguration.java | 0 .../IKeystoreAndCertificateProperties.java | 0 .../KeystoreAndCertificateProperties.java | 0 .../gr/iccs/imu/ems/util/KeystoreUtil.java | 4 +- .../java/gr/iccs/imu/ems/util/NetUtil.java | 0 .../imu/ems/util/NetUtilPostProcessor.java | 0 .../gr/iccs/imu/ems/util/PasswordUtil.java | 0 .../java/gr/iccs/imu/ems/util/Plugin.java | 0 .../iccs/imu/ems/util/SerializationUtil.java | 0 .../java/gr/iccs/imu/ems/util/StrUtil.java | 2 +- .../password/AsterisksPasswordEncoder.java | 0 .../password/IdentityPasswordEncoder.java | 0 .../ems/util/password/PasswordEncoder.java | 0 .../util/password/PresentPasswordEncoder.java | 0 .../ems-core}/web-admin/.dockerignore | 0 .../ems-core}/web-admin/.gitignore | 0 .../ems-core}/web-admin/Dockerfile | 0 .../ems-core}/web-admin/README.md | 0 .../ems-core}/web-admin/babel.config.js | 0 .../ems-core}/web-admin/package.json | 0 .../ems-core}/web-admin/pom.xml | 0 .../public/assets/css/adminlte.min.css | 0 .../img/circuit-board-5907811_1920-bw.png | Bin .../public/assets/img/ems-logo-192x192.png | Bin .../assets/img/wave-loader-green-sm.gif | Bin .../public/assets/img/wave-loader-green.gif | Bin .../public/assets/img/wave-loader-grey-sm.gif | Bin .../public/assets/img/wave-loader-grey.gif | Bin .../web-admin/public/assets/js/adminlte.js | 0 .../public/assets/js/adminlte.js.map | 0 .../public/assets/js/adminlte.min.js | 0 .../public/assets/js/adminlte.min.js.map | 0 .../plugins/bootstrap/css/bootstrap.min.css | 0 .../bootstrap/css/bootstrap.min.css.map | 0 .../plugins/bootstrap/js/bootstrap.bundle.js | 0 .../bootstrap/js/bootstrap.bundle.js.map | 0 .../bootstrap/js/bootstrap.bundle.min.js | 0 .../bootstrap/js/bootstrap.bundle.min.js.map | 0 .../plugins/fontawesome-free/css/all.css | 0 .../plugins/fontawesome-free/css/all.min.css | 0 .../plugins/fontawesome-free/css/brands.css | 0 .../fontawesome-free/css/brands.min.css | 0 .../fontawesome-free/css/fontawesome.css | 0 .../fontawesome-free/css/fontawesome.min.css | 0 .../plugins/fontawesome-free/css/regular.css | 0 .../fontawesome-free/css/regular.min.css | 0 .../plugins/fontawesome-free/css/solid.css | 0 .../fontawesome-free/css/solid.min.css | 0 .../fontawesome-free/css/svg-with-js.css | 0 .../fontawesome-free/css/svg-with-js.min.css | 0 .../plugins/fontawesome-free/css/v4-shims.css | 0 .../fontawesome-free/css/v4-shims.min.css | 0 .../assets/plugins/fontawesome-free/js/all.js | 0 .../plugins/fontawesome-free/js/all.min.js | 0 .../plugins/fontawesome-free/js/brands.js | 0 .../plugins/fontawesome-free/js/brands.min.js | 0 .../fontawesome-free/js/conflict-detection.js | 0 .../js/conflict-detection.min.js | 0 .../fontawesome-free/js/fontawesome.js | 0 .../fontawesome-free/js/fontawesome.min.js | 0 .../plugins/fontawesome-free/js/regular.js | 0 .../fontawesome-free/js/regular.min.js | 0 .../plugins/fontawesome-free/js/solid.js | 0 .../plugins/fontawesome-free/js/solid.min.js | 0 .../plugins/fontawesome-free/js/v4-shims.js | 0 .../fontawesome-free/js/v4-shims.min.js | 0 .../webfonts/fa-brands-400.eot | Bin .../webfonts/fa-brands-400.svg | 0 .../webfonts/fa-brands-400.ttf | Bin .../webfonts/fa-brands-400.woff | Bin .../webfonts/fa-brands-400.woff2 | Bin .../webfonts/fa-regular-400.eot | Bin .../webfonts/fa-regular-400.svg | 0 .../webfonts/fa-regular-400.ttf | Bin .../webfonts/fa-regular-400.woff | Bin .../webfonts/fa-regular-400.woff2 | Bin .../webfonts/fa-solid-900.eot | Bin .../webfonts/fa-solid-900.svg | 0 .../webfonts/fa-solid-900.ttf | Bin .../webfonts/fa-solid-900.woff | Bin .../webfonts/fa-solid-900.woff2 | Bin .../assets/plugins/jquery/jquery.min.js | 0 .../plugins/jquery/jquery.slimscroll.min.js | 0 .../ems-core}/web-admin/public/favicon.ico | Bin .../ems-core}/web-admin/public/index.html | 0 .../ems-core}/web-admin/public/login.html | 0 .../ems-core}/web-admin/src/App.vue | 0 .../circuit-board-5907811_1920-bw.png | Bin .../src/assets/img/ems-logo-192x192.png | Bin .../web-admin/src/assets/img/ems-logo.png | Bin .../web-admin/src/assets/img/ems-logo.svg | 0 .../web-admin/src/assets/img/party.gif | Bin .../web-admin/src/components/7seg/7seg.vue | 0 .../DSEG14-Classic/DSEG14Classic-Bold.woff2 | Bin .../DSEG14Classic-BoldItalic.woff2 | Bin .../DSEG14-Classic/DSEG14Classic-Italic.woff2 | Bin .../DSEG14Classic-Regular.woff2 | Bin .../DSEG14-Modern/DSEG14Modern-Bold.woff2 | Bin .../DSEG14Modern-BoldItalic.woff2 | Bin .../DSEG14-Modern/DSEG14Modern-Italic.woff2 | Bin .../DSEG14-Modern/DSEG14Modern-Regular.woff2 | Bin .../DSEG7-Classic/DSEG7Classic-Bold.woff2 | Bin .../DSEG7Classic-BoldItalic.woff2 | Bin .../DSEG7-Classic/DSEG7Classic-Italic.woff2 | Bin .../DSEG7-Classic/DSEG7Classic-Regular.woff2 | Bin .../7seg/DSEG7-Modern/DSEG7Modern-Bold.woff2 | Bin .../DSEG7-Modern/DSEG7Modern-BoldItalic.woff2 | Bin .../DSEG7-Modern/DSEG7Modern-Italic.woff2 | Bin .../DSEG7-Modern/DSEG7Modern-Regular.woff2 | Bin .../src/components/ace-editor/ace-editor.vue | 0 .../web-admin/src/components/card/card.html | 0 .../web-admin/src/components/card/card.js | 0 .../web-admin/src/components/card/card.vue | 0 .../src/components/chartjs/chartjs.vue | 0 .../web-admin/src/components/clock/clock.vue | 0 .../src/components/ems/sse/ems-sse.vue | 0 .../web-admin/src/components/ems/ts/ts.js | 0 .../src/components/infobox/infobox.html | 0 .../src/components/infobox/infobox.js | 0 .../src/components/infobox/infobox.vue | 0 .../src/components/jqvmap/jqvmap.vue | 0 .../src/components/jvectormap/jvectormap.vue | 0 .../web-admin/src/components/knob/knob.vue | 0 .../components/leaflet-map/leaflet-map.vue | 0 .../web-admin/src/components/modal/modal.vue | 0 .../src/components/smallbox/smallbox.html | 0 .../src/components/smallbox/smallbox.js | 0 .../src/components/smallbox/smallbox.vue | 0 .../src/components/sparkline/sparkline.vue | 0 .../src/components/status-led/status-led.vue | 0 .../src/components/worldmap/WorldMap.vue | 0 .../src/components/worldmap/countries.js | 0 .../ems-core}/web-admin/src/main.js | 0 .../ems-core}/web-admin/src/resources/.env | 0 .../ems-core}/web-admin/src/router.js | 0 .../ems-core}/web-admin/src/utils.js | 0 .../ems-core}/web-admin/src/views/404.vue | 0 .../ems-core}/web-admin/src/views/about.vue | 0 .../views/admin/admin-1-overview-header.vue | 0 .../src/views/admin/admin-1-overview.vue | 0 .../src/views/admin/admin-1-overview.vue.old | 0 .../src/views/admin/admin-2-topology.vue | 0 .../src/views/admin/admin-3-geography.vue | 0 .../src/views/admin/admin-4-commands.vue | 0 .../src/views/admin/admin-5-broker-cep.vue | 0 .../web-admin/src/views/admin/admin.vue | 0 .../src/views/admin/country-coordinates.js | 0 .../web-admin/src/views/admin/old/admin.html | 0 .../web-admin/src/views/admin/old/admin.js | 0 .../web-admin/src/views/admin/old/admin.vue | 0 .../src/views/admin/widgets/cdo-mgnt.vue | 0 .../views/admin/widgets/client-commands.vue | 0 .../src/views/admin/widgets/client-events.vue | 0 .../src/views/admin/widgets/clients-list.vue | 0 .../src/views/admin/widgets/command-input.vue | 0 .../views/admin/widgets/destinations-list.vue | 0 .../src/views/admin/widgets/fileexplorer.vue | 0 .../src/views/admin/widgets/img/blank-64.png | Bin .../admin/widgets/img/camel-model-32.png | Bin .../admin/widgets/img/camel-model-64.png | Bin .../admin/widgets/img/camel-model-80.png | Bin .../views/admin/widgets/img/cp-model-32.png | Bin .../views/admin/widgets/img/cp-model-64.png | Bin .../src/views/admin/widgets/img/folder-64.png | Bin .../views/admin/widgets/img/unknown-64.png | Bin .../src/views/admin/widgets/latest-events.vue | 0 .../views/admin/widgets/node-actions-list.vue | 0 .../views/admin/widgets/rest-call-forms.js | 15 +- .../src/views/admin/widgets/rest-call.vue | 0 .../src/views/admin/widgets/textarea-dnd.vue | 0 .../control-sidebar/control-sidebar.html | 0 .../common/control-sidebar/control-sidebar.js | 0 .../control-sidebar/control-sidebar.vue | 0 .../src/views/common/footer/footer.html | 0 .../src/views/common/footer/footer.js | 0 .../src/views/common/footer/footer.vue | 0 .../src/views/common/header/header.html | 2 +- .../src/views/common/header/header.js | 0 .../src/views/common/header/header.vue | 0 .../common/menu-sidebar/menu-sidebar.html | 0 .../views/common/menu-sidebar/menu-sidebar.js | 0 .../common/menu-sidebar/menu-sidebar.vue | 0 .../src/views/common/section/section.vue | 0 .../title-and-breadcrumb.vue | 0 .../connection-info/connection-info.vue | 0 .../widgets/connection-info/img/plug-blue.png | Bin .../connection-info/img/plug-green.png | Bin .../connection-info/img/plug-orange.png | Bin .../widgets/connection-info/img/plug-red.png | Bin .../widgets/connection-info/img/wave-blue.gif | Bin .../connection-info/img/wave-green.gif | Bin .../connection-info/img/wave-orange.gif | Bin .../widgets/connection-info/img/wave-red.gif | Bin .../widgets/health-info/health-info.vue | 0 .../widgets/notifications/notifications.html | 0 .../widgets/notifications/notifications.js | 0 .../widgets/notifications/notifications.vue | 0 .../views/common/widgets/search/search.vue | 0 .../web-admin/src/views/sample/sample.html | 0 .../web-admin/src/views/sample/sample.js | 0 .../web-admin/src/views/sample/sample.vue | 0 .../ems-core}/web-admin/vue.config.js | 0 nebulous/ems-nebulous/.gitattributes | 12 + nebulous/ems-nebulous/.gitignore | 38 + nebulous/ems-nebulous/LICENSE | 373 +++++++ nebulous/ems-nebulous/pom.xml | 316 ++++++ .../plugins/PredictionInfoBeaconPlugin.java | 107 ++ .../PredictionsPostTranslationPlugin.java | 238 +++++ .../ems/translate/ModelException.java | 15 + .../NebulousEmsTranslationException.java | 23 + .../ems/translate/NebulousEmsTranslator.java | 137 +++ .../NebulousEmsTranslatorProperties.java | 57 ++ .../ems/translate/TranslatorApplication.java | 78 ++ .../ems/translate/analyze/AbstractHelper.java | 21 + .../ems/translate/analyze/AnalysisUtils.java | 222 ++++ .../translate/analyze/ConstraintsHelper.java | 218 ++++ .../translate/analyze/FunctionsHelper.java | 67 ++ .../analyze/MetricModelAnalyzer.java | 350 +++++++ .../analyze/MetricModelValidator.java | 135 +++ .../ems/translate/analyze/MetricsHelper.java | 509 ++++++++++ .../ems/translate/analyze/NamesKey.java | 34 + .../translate/analyze/NodeUpdatingHelper.java | 198 ++++ .../ems/translate/analyze/SensorsHelper.java | 228 +++++ .../analyze/ShorthandsExpansionHelper.java | 208 ++++ .../ems/translate/generate/RuleGenerator.java | 960 ++++++++++++++++++ .../generate/RuleTemplateRegistry.java | 67 ++ .../plugins/NetdataPostProcessorPlugin.java | 41 + .../plugins/SensorPostProcessorPlugin.java | 15 + .../translate/transform/GraphTransformer.java | 107 ++ .../resources/metric-model-schematron.xml | 16 + .../src/main/resources/rule-templates.yml | 236 +++++ .../nebulous-metric-model-schema.json | 679 +++++++++++++ .../nebulous-metric-model-v1.0.0-schema.json | 679 +++++++++++++ nebulous/pom.xml | 25 + zuul.d/jobs.yaml | 10 +- 604 files changed, 7900 insertions(+), 1041 deletions(-) create mode 100644 .gitattributes delete mode 100644 ems-core/common/src/main/resources/META-INF/spring.factories delete mode 100644 ems-core/translator/src/main/resources/banner-alternative.txt delete mode 100644 ems-core/translator/src/main/resources/banner.txt delete mode 100644 ems-core/translator/src/main/resources/rule-templates.yml create mode 100644 nebulous/Dockerfile rename {ems-core => nebulous/ems-core}/.gitattributes (100%) rename {ems-core => nebulous/ems-core}/.gitignore (100%) rename {ems-core => nebulous/ems-core}/README-for-TESTING.md (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/pom.xml (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationProperties.java (97%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationRequestListener.java (55%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationTask.java (92%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstaller.java (79%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallerPlugin.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/InstallationContextProcessorPlugin.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshClientInstaller.java (98%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshConfig.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshJsClientInstaller.java (99%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/StreamLogger.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/api/INodeRegistration.java (74%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/AbstractInstallationHelper.java (99%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelper.java (93%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelperFactory.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/VmInstallationHelper.java (97%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/AbstractInstructionsBase.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_RESULT.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_TYPE.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/Instruction.java (98%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsService.java (98%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsSet.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/AllowedTopicsProcessorPlugin.java (89%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/PrometheusProcessorPlugin.java (98%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ClientRecoveryPlugin.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/SelfHealingManagerImpl.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ServerSelfHealingProperties.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/LICENSE (100%) rename {ems-core => nebulous/ems-core}/baguette-client/bin/baguette-client (100%) rename {ems-core => nebulous/ems-core}/baguette-client/bin/client.sh (100%) rename {ems-core => nebulous/ems-core}/baguette-client/bin/install.sh (100%) rename {ems-core => nebulous/ems-core}/baguette-client/bin/kill.sh (100%) rename {ems-core => nebulous/ems-core}/baguette-client/bin/run.bat (100%) rename {ems-core => nebulous/ems-core}/baguette-client/bin/run.sh (100%) rename {ems-core => nebulous/ems-core}/baguette-client/conf/baguette-client.properties.sample (100%) rename {ems-core => nebulous/ems-core}/baguette-client/conf/baguette-client.yml (100%) rename {ems-core => nebulous/ems-core}/baguette-client/conf/baguette.json (100%) rename {ems-core => nebulous/ems-core}/baguette-client/conf/logback-spring.xml (100%) rename {ems-core => nebulous/ems-core}/baguette-client/conf/netdata.json (100%) rename {ems-core => nebulous/ems-core}/baguette-client/logs/output.txt (100%) rename {ems-core => nebulous/ems-core}/baguette-client/pom.xml (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/assembly/baguette-client-installation-package.xml (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClient.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientCLI.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientProperties.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Collector.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/CommandExecutor.java (98%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Sshc.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/AbstractLogBase.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/BrokerUtil.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterCLI.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManager.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManagerProperties.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterTest.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberScoreFunction.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberWithScore.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/TestCallback.java (97%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/ClientCollectorContext.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/netdata/NetdataCollector.java (78%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/prometheus/PrometheusCollector.java (78%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/NodeInfoHelper.java (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/SelfHealingPlugin.java (98%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/resources/META-INF/spring.factories (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/resources/banner-1.txt (100%) rename {ems-core => nebulous/ems-core}/baguette-client/src/main/resources/banner.txt (100%) rename {ems-core => nebulous/ems-core}/baguette-server/pom.xml (93%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/BaguetteServer.java (99%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ClientShellCommand.java (98%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/GroupingConfigurationHelper.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistry.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistryEntry.java (96%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ServerCoordinator.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/Sshd.java (99%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/NoopCoordinator.java (92%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorTimeWin.java (96%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorWaitAll.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TestCoordinator.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TwoLevelCoordinator.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/AtLeastTwoZoneManagementStrategy.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterSelfHealing.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZone.java (99%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZoneDetector.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusteringCoordinator.java (99%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/DefaultZoneManagementStrategy.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZone.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZoneDetector.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IZoneManagementStrategy.java (100%) rename {ems-core => nebulous/ems-core}/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/properties/BaguetteServerProperties.java (97%) rename {ems-core => nebulous/ems-core}/bin/client.sh (100%) rename {ems-core => nebulous/ems-core}/bin/cp2cdo.bat (100%) rename {ems-core => nebulous/ems-core}/bin/cp2cdo.sh (100%) rename {ems-core => nebulous/ems-core}/bin/detect.sh (100%) rename {ems-core => nebulous/ems-core}/bin/initialize-MELODIC-keystores.sh (100%) rename {ems-core => nebulous/ems-core}/bin/initialize-keystores.bat (100%) rename {ems-core => nebulous/ems-core}/bin/initialize-keystores.sh (100%) rename {ems-core => nebulous/ems-core}/bin/jwtutil.bat (94%) rename {ems-core => nebulous/ems-core}/bin/jwtutil.sh (95%) rename {ems-core => nebulous/ems-core}/bin/run.bat (98%) rename {ems-core => nebulous/ems-core}/bin/run.sh (98%) rename {ems-core => nebulous/ems-core}/bin/sysmon.sh (100%) rename {ems-core => nebulous/ems-core}/bin/update-credentials.sh (100%) rename {ems-core => nebulous/ems-core}/broker-cep/client.bat (100%) rename {ems-core => nebulous/ems-core}/broker-cep/pom.xml (97%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/BrokerCepConsumer.java (99%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/BrokerCepService.java (98%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/BrokerCepStatementSubscriber.java (98%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/EventCache.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/EventForwarder.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/BrokerAdvisoryWatcher.java (97%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/BrokerConfig.java (99%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/InterceptorHelper.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/SimpleBrokerAuthorizationPlugin.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/interceptor/AbstractMessageInterceptor.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/interceptor/CompositeInterceptor.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/interceptor/LogMessageUpdateInterceptor.java (94%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/interceptor/MessageForwarderInterceptor.java (99%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/interceptor/NodePropertiesMessageUpdateInterceptor.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/interceptor/SequentialCompositeInterceptor.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/broker/interceptor/SourceAddressMessageUpdateInterceptor.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/cep/CepEvalAggregator.java (96%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/cep/CepEvalAggregatorFactory.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/cep/CepEvalFunction.java (95%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/cep/CepExtensions.java (95%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/cep/CepService.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/cep/MathUtil.java (96%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/cep/StatementSubscriber.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/event/EventMap.java (94%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/event/EventRecorder.java (95%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/properties/BrokerCepProperties.java (100%) rename {ems-core => nebulous/ems-core}/broker-cep/src/main/java/gr/iccs/imu/ems/brokercep/properties/NodeProperties.java (100%) rename {ems-core => nebulous/ems-core}/broker-client/client.bat (100%) rename {ems-core => nebulous/ems-core}/broker-client/client.sh (100%) rename {ems-core => nebulous/ems-core}/broker-client/pom.xml (97%) rename {ems-core => nebulous/ems-core}/broker-client/src/main/java/gr/iccs/imu/ems/brokerclient/BrokerClient.java (98%) rename {ems-core => nebulous/ems-core}/broker-client/src/main/java/gr/iccs/imu/ems/brokerclient/BrokerClientApp.java (96%) rename {ems-core => nebulous/ems-core}/broker-client/src/main/java/gr/iccs/imu/ems/brokerclient/event/EventGenerator.java (98%) rename {ems-core => nebulous/ems-core}/broker-client/src/main/java/gr/iccs/imu/ems/brokerclient/event/EventMap.java (100%) rename {ems-core => nebulous/ems-core}/broker-client/src/main/java/gr/iccs/imu/ems/brokerclient/properties/BrokerClientProperties.java (100%) rename {ems-core => nebulous/ems-core}/broker-client/src/main/resources/logback.xml (100%) rename {ems-core => nebulous/ems-core}/common/pom.xml (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/client/SshClient.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/client/SshClientProperties.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/AbstractEndpointCollector.java (81%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/AbstractEndpointCollectorProperties.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/CollectorContext.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/netdata/NetdataCollector.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/netdata/NetdataCollectorProperties.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/prometheus/OpenMetricsParser.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/prometheus/PrometheusCollector.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/collector/prometheus/PrometheusCollectorProperties.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/misc/EventConstant.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/misc/SystemResourceMonitor.java (91%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/plugin/PluginManager.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/AbstractRecoveryTask.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/EmsClientRecoveryTask.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/NetdataAgentLocalRecoveryTask.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/NetdataAgentRecoveryTask.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/RECOVERY_COMMAND.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/RecoveryConstant.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/RecoveryContext.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/RecoveryTask.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/SelfHealingProperties.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/ShellRecoveryTask.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/recovery/VmNodeRecoveryTask.java (100%) rename {ems-core => nebulous/ems-core}/common/src/main/java/gr/iccs/imu/ems/common/selfhealing/SelfHealingManager.java (100%) create mode 100644 nebulous/ems-core/common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/baguette-skip.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/baguette.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/check-ignore.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/detect.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/jre.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/netdata.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/recover-baguette.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/start-agents.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux-yaml/stop-agents.yml (98%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/baguette-remove.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/baguette-skip.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/baguette.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/check-ignore.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/detect.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/jre.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/netdata.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/recover-baguette.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/linux/start-agents.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/netdata/go.d/prometheus.conf (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client-install/win/win.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client/conf/baguette-client.properties.sample (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client/conf/baguette-client.yml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client/conf/baguette.json (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client/conf/logback-spring.xml (100%) rename {ems-core => nebulous/ems-core}/config-files/baguette-client/conf/netdata.json (100%) rename {ems-core => nebulous/ems-core}/config-files/ems-server.properties.sample (97%) rename {ems-core => nebulous/ems-core}/config-files/ems-server.yml (97%) rename {ems-core => nebulous/ems-core}/config-files/eu.melodic.upperware.security.properties (100%) rename {ems-core => nebulous/ems-core}/config-files/eu.paasage.mddb.cdo.client.properties (100%) rename {ems-core => nebulous/ems-core}/config-files/logback-conf/logback-spring.xml (100%) rename {ems-core => nebulous/ems-core}/config-files/secrets.properties (100%) rename {ems-core => nebulous/ems-core}/control-service/pom.xml (93%) rename {ems-core => nebulous/ems-core}/control-service/src/main/docker/Dockerfile (62%) rename {ems-core => nebulous/ems-core}/control-service/src/main/docker/Dockerfile-alpine (76%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/ApplicationContext.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/ControlServiceApplication.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/collector/Collector.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/collector/ServerCollectorContext.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/collector/netdata/ServerNetdataCollector.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/BrokerCepController.java (84%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceController.java (76%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceCoordinator.java (92%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceRequestInfo.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsController.java (84%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsCoordinator.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementController.java (73%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementCoordinator.java (98%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationController.java (67%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationCoordinator.java (84%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerException.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerExceptionHandler.java (91%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/BuildInfoProvider.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceBuildInfoEndpoint.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceHealthIndicator.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceInfoEndpointExtension.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceLiveInfoEndpoint.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMBean.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMetrics.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/EmsInfoServiceImpl.java (99%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesController.java (99%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesDisabledController.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoProvider.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoService.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/InfoServiceController.java (95%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/info/SystemInfoProvider.java (89%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/BeaconPlugin.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/EmsInfoPlugin.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/MetasolverPlugin.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/PostTranslationPlugin.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/TranslationContextPlugin.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/WebAdminPlugin.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopBeaconPlugin.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopPostTranslationPlugin.java (96%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopTranslationContextPlugin.java (96%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/properties/ControlServiceProperties.java (98%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/properties/InfoServiceProperties.java (96%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/properties/StaticResourceProperties.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/properties/TopicBeaconProperties.java (97%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/properties/WebSecurityProperties.java (91%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/EventBusCache.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/NodeRegistrationHelper.java (62%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/TopicBeacon.java (89%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/TranslationContextMonitorGsonDeserializer.java (93%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/WebClientUtil.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenProperties.java (93%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenService.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenUtil.java (98%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/util/mvv/NoopMetricVariableValuesServiceImpl.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/StaticResourceConfiguration.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebMvcConfig.java (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebSecurityConfig.java (98%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/META-INF/spring.factories (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/banner-0.txt (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/banner-1.txt (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/banner.txt (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/public/client.bat (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/public/client.sh (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/public/favicon.ico (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/public/index.html (100%) rename {ems-core => nebulous/ems-core}/control-service/src/main/resources/version.txt (100%) rename {ems-core => nebulous/ems-core}/pom.xml (93%) rename {ems-core => nebulous/ems-core}/translator/pom.xml (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/Grouping.java (97%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/NoopTranslator.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContext.java (88%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinter.java (79%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinterProperties.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/Translator.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/TranslatorApplication.java_OFF (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAG.java (74%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGEdge.java (100%) create mode 100644 nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGExporter.java rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGNode.java (87%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractInterfaceRootObject.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractRootObject.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Action.java (92%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Annotation.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Attribute.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryEventPattern.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryPatternOperatorType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/BooleanValue.java (93%) rename ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LoadMetricVariable.java => nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BusyStatusMetricVariable.java (79%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/ComparisonOperatorType.java (75%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Component.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeConstraint.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetric.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetricContext.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Constraint.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/CriterionType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Data.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/DataSource.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/DoubleValue.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Event.java (92%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/EventPattern.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Feature.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/FloatValue.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Function.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/GroupingType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/IfThenConstraint.java (95%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/IntValue.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Interval.java (97%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalConstraint.java (89%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalOperatorType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/MeasurableAttribute.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Metric.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricConstraint.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricContext.java (95%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricTemplate.java (62%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariable.java (95%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariableConstraint.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Monitor.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/NamedElement.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/NonFunctionalEvent.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/NumericValue.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/ObjectContext.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/OptimisationRequirement.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/PullSensor.java (83%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/PushSensor.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetric.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetricContext.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Requirement.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalabilityRule.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalingAction.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Schedule.java (79%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sensor.java (77%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/ServiceLevelObjective.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/SingleEvent.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sink.java (95%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/StringValue.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Timer.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/TimerType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryConstraint.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryEventPattern.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryPatternOperatorType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Value.java (93%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/ValueType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/VariableType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/Window.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowCriterion.java (94%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessing.java (95%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessingType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowSizeType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowType.java (100%) rename {ems-core => nebulous/ems-core}/translator/src/main/java/gr/iccs/imu/ems/translate/mvv/MetricVariableValuesService.java (100%) rename {ems-core => nebulous/ems-core}/util/pom.xml (98%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/ClientConfiguration.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMap.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMapConverter.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/EmsConstant.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/EventBus.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/FunctionDefinition.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/GROUPING.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/GroupingConfiguration.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/IKeystoreAndCertificateProperties.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/KeystoreAndCertificateProperties.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/KeystoreUtil.java (99%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/NetUtil.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/NetUtilPostProcessor.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/PasswordUtil.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/Plugin.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/SerializationUtil.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/StrUtil.java (99%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/password/AsterisksPasswordEncoder.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/password/IdentityPasswordEncoder.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/password/PasswordEncoder.java (100%) rename {ems-core => nebulous/ems-core}/util/src/main/java/gr/iccs/imu/ems/util/password/PresentPasswordEncoder.java (100%) rename {ems-core => nebulous/ems-core}/web-admin/.dockerignore (100%) rename {ems-core => nebulous/ems-core}/web-admin/.gitignore (100%) rename {ems-core => nebulous/ems-core}/web-admin/Dockerfile (100%) rename {ems-core => nebulous/ems-core}/web-admin/README.md (100%) rename {ems-core => nebulous/ems-core}/web-admin/babel.config.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/package.json (100%) rename {ems-core => nebulous/ems-core}/web-admin/pom.xml (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/css/adminlte.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/img/circuit-board-5907811_1920-bw.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/img/ems-logo-192x192.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/img/wave-loader-green-sm.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/img/wave-loader-green.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/img/wave-loader-grey-sm.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/img/wave-loader-grey.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/js/adminlte.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/js/adminlte.js.map (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/js/adminlte.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/js/adminlte.min.js.map (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css.map (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js.map (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js.map (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/all.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/all.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/brands.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/brands.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/regular.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/regular.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/solid.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/solid.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.min.css (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/all.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/all.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/brands.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/brands.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/regular.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/regular.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/solid.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/solid.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.eot (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.svg (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.ttf (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.eot (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.svg (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.ttf (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.eot (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.svg (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.ttf (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/jquery/jquery.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/assets/plugins/jquery/jquery.slimscroll.min.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/favicon.ico (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/index.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/public/login.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/App.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/assets/img/backgrounds/circuit-board-5907811_1920-bw.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/assets/img/ems-logo-192x192.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/assets/img/ems-logo.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/assets/img/ems-logo.svg (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/assets/img/party.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/7seg.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Bold.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-BoldItalic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Italic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Regular.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Bold.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-BoldItalic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Italic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Regular.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Bold.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-BoldItalic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Italic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Regular.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Bold.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-BoldItalic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Italic.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Regular.woff2 (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/ace-editor/ace-editor.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/card/card.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/card/card.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/card/card.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/chartjs/chartjs.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/clock/clock.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/ems/sse/ems-sse.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/ems/ts/ts.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/infobox/infobox.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/infobox/infobox.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/infobox/infobox.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/jqvmap/jqvmap.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/jvectormap/jvectormap.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/knob/knob.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/leaflet-map/leaflet-map.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/modal/modal.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/smallbox/smallbox.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/smallbox/smallbox.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/smallbox/smallbox.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/sparkline/sparkline.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/status-led/status-led.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/worldmap/WorldMap.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/components/worldmap/countries.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/main.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/resources/.env (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/router.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/utils.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/404.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/about.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin-1-overview-header.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin-1-overview.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin-1-overview.vue.old (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin-2-topology.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin-3-geography.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin-4-commands.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin-5-broker-cep.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/admin.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/country-coordinates.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/old/admin.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/old/admin.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/old/admin.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/cdo-mgnt.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/client-commands.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/client-events.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/clients-list.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/command-input.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/destinations-list.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/fileexplorer.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/blank-64.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/camel-model-32.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/camel-model-64.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/camel-model-80.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/cp-model-32.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/cp-model-64.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/folder-64.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/img/unknown-64.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/latest-events.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/node-actions-list.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/rest-call-forms.js (88%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/rest-call.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/admin/widgets/textarea-dnd.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/control-sidebar/control-sidebar.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/control-sidebar/control-sidebar.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/control-sidebar/control-sidebar.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/footer/footer.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/footer/footer.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/footer/footer.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/header/header.html (97%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/header/header.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/header/header.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/menu-sidebar/menu-sidebar.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/menu-sidebar/menu-sidebar.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/menu-sidebar/menu-sidebar.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/section/section.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/title-and-breadcrumb/title-and-breadcrumb.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/connection-info.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/plug-blue.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/plug-green.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/plug-orange.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/plug-red.png (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/wave-blue.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/wave-green.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/wave-orange.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/connection-info/img/wave-red.gif (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/health-info/health-info.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/notifications/notifications.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/notifications/notifications.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/notifications/notifications.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/common/widgets/search/search.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/sample/sample.html (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/sample/sample.js (100%) rename {ems-core => nebulous/ems-core}/web-admin/src/views/sample/sample.vue (100%) rename {ems-core => nebulous/ems-core}/web-admin/vue.config.js (100%) create mode 100644 nebulous/ems-nebulous/.gitattributes create mode 100644 nebulous/ems-nebulous/.gitignore create mode 100644 nebulous/ems-nebulous/LICENSE create mode 100644 nebulous/ems-nebulous/pom.xml create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionInfoBeaconPlugin.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionsPostTranslationPlugin.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/ModelException.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslationException.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslator.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslatorProperties.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/TranslatorApplication.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AbstractHelper.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AnalysisUtils.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ConstraintsHelper.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/FunctionsHelper.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelAnalyzer.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelValidator.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricsHelper.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NamesKey.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NodeUpdatingHelper.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/SensorsHelper.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ShorthandsExpansionHelper.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleGenerator.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleTemplateRegistry.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/NetdataPostProcessorPlugin.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/SensorPostProcessorPlugin.java create mode 100644 nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/transform/GraphTransformer.java create mode 100644 nebulous/ems-nebulous/src/main/resources/metric-model-schematron.xml create mode 100644 nebulous/ems-nebulous/src/main/resources/rule-templates.yml create mode 100644 nebulous/metric-model/nebulous-metric-model-schema.json create mode 100644 nebulous/metric-model/nebulous-metric-model-v1.0.0-schema.json create mode 100644 nebulous/pom.xml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..94f480d --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore index e0e9b8b..768b37c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,15 @@ -__pycache__/ -.nox/ +target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr diff --git a/charts/nebulous-monitoring/values.yaml b/charts/nebulous-monitoring/values.yaml index c9263fd..8872aea 100644 --- a/charts/nebulous-monitoring/values.yaml +++ b/charts/nebulous-monitoring/values.yaml @@ -5,7 +5,7 @@ replicaCount: 1 image: - repository: "quay.io/nebulous/monitoring-java-spring-boot-demo" + repository: "quay.io/nebulous/monitoring" pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "" diff --git a/ems-core/common/src/main/resources/META-INF/spring.factories b/ems-core/common/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 5268298..0000000 --- a/ems-core/common/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=plugin.gr.iccs.imu.ems.common.PluginManager \ No newline at end of file diff --git a/ems-core/translator/src/main/resources/banner-alternative.txt b/ems-core/translator/src/main/resources/banner-alternative.txt deleted file mode 100644 index 80fb379..0000000 --- a/ems-core/translator/src/main/resources/banner-alternative.txt +++ /dev/null @@ -1,7 +0,0 @@ - ______ __ ___ __________ __ - / ____/___ _____ ___ ___ / / |__ \ / ____/ __ \/ / - / / / __ `/ __ `__ \/ _ \/ / __/ / / __/ / /_/ / / -/ /___/ /_/ / / / / / / __/ / / __/ / /___/ ____/ /___ -\____/\__,_/_/ /_/ /_/\___/_/ /____/ /_____/_/ /_____/ - - \ No newline at end of file diff --git a/ems-core/translator/src/main/resources/banner.txt b/ems-core/translator/src/main/resources/banner.txt deleted file mode 100644 index efd1f4e..0000000 --- a/ems-core/translator/src/main/resources/banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - _____ _ ___ ______ _____ _ - / ____| | | |__ \ | ____| __ \| | - | | __ _ _ __ ___ ___| | ) | | |__ | |__) | | - | | / _` | '_ ` _ \ / _ \ | / / | __| | ___/| | - | |___| (_| | | | | | | __/ | / /_ | |____| | | |____ - \_____\__,_|_| |_| |_|\___|_| |____| |______|_| |______| - - \ No newline at end of file diff --git a/ems-core/translator/src/main/resources/rule-templates.yml b/ems-core/translator/src/main/resources/rule-templates.yml deleted file mode 100644 index 65d85d3..0000000 --- a/ems-core/translator/src/main/resources/rule-templates.yml +++ /dev/null @@ -1,237 +0,0 @@ -# -# Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr) -# -# This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless -# Esper library is used, in which case it is subject to the terms of General Public License v2.0. -# If a copy of the MPL was not distributed with this file, you can obtain one at -# https://www.mozilla.org/en-US/MPL/2.0/ -# - -# EPL Rule templates per Element-Type and Monitoring-Grouping - -DOLLAR: '$' -translator.generator: - language: EPL - rule-templates: - # SCHEDULE (i.e. IUTPUT) CLAUSE - SCHEDULE: - __ANY__: - - | - OUTPUT ALL EVERY [(${DOLLAR}{period})] [(${DOLLAR}{unit})] - AGG: - - | - OUTPUT SNAPSHOT EVERY [(${DOLLAR}{period})] [(${DOLLAR}{unit})] - # Binary-Event-Pattern templates - BEP-AND: - GLOBAL: - - | - /* BEP-AND-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT le.* FROM [(${DOLLAR}{leftEvent})].std:lastevent() AS le, [(${DOLLAR}{rightEvent})].std:lastevent() AS re - BEP-OR: - GLOBAL: -#XXX: TEST: - - | - /* BEP-OR-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT CASE WHEN le IS NULL THEN re ELSE le END AS evt FROM PATTERN [ EVERY ( le=[(${DOLLAR}{leftEvent})] OR re=[(${DOLLAR}{rightEvent})] ) ] - BEP-XOR: -#XXX: XOR is NOT SUPPORTED: IS IT EQUIVALENT TO OR?? - GLOBAL: -#XXX: TEST: - - | - /* BEP-XOR-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT CASE WHEN le IS NULL THEN re ELSE le END AS evt FROM PATTERN [ EVERY ( le=[(${DOLLAR}{leftEvent})] OR re=[(${DOLLAR}{rightEvent})] ) ] - BEP-PRECEDES: - GLOBAL: -#XXX: TEST: - - | - /* BEP-PRECEDES-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT le.* FROM PATTERN [ EVERY ( le=[(${DOLLAR}{leftEvent})] -> re=[(${DOLLAR}{rightEvent})] ) ] - BEP-REPEAT_UNTIL: - GLOBAL: -#XXX: TEST: - - | - /* BEP-REPEAT_UNTIL-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT re.* FROM PATTERN [ EVERY [ le=[(${DOLLAR}{leftEvent})] UNTIL re=[(${DOLLAR}{rightEvent})] ] ] WHERE le IS NOT NULL - - # Unary-Event-Pattern templates - UEP-EVERY: -#XXX: WHAT'S THE MEANING OF THIS OPERATOR?? ...IF STANDALONE?? - GLOBAL: - - | - /* UEP-EVERY-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT ue.* FROM PATTERN [ EVERY ue=[(${DOLLAR}{unaryEvent})] ] - UEP-NOT: -#XXX: WHAT'S THE MEANING OF THIS OPERATOR?? ...IF STANDALONE?? - GLOBAL: - - | - /* UEP-NOT-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT ue.* FROM PATTERN [ NOT ue=[(${DOLLAR}{unaryEvent})] ] - UEP-REPEAT: - GLOBAL: -#XXX: TEST: - - | - /* UEP-REPEAT-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT ue[0].* FROM PATTERN [ [[(${DOLLAR}{occurrenceNum})]] ue=[(${DOLLAR}{unaryEvent})] ] - UEP-WHEN: -#XXX: WHAT'S THE MEANING OF THIS OPERATOR?? ...IF STANDALONE?? - GLOBAL: - - | - /* UEP-WHEN-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT ue.* FROM [(${DOLLAR}{leftEvent})].std:lastevent() AS ue - - # Non-Functional-Event templates - NFE: - GLOBAL: - - | - /* NFE-GLOBAL */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT * FROM [(${DOLLAR}{metricConstraint})].std:lastevent() - - # Metric-Constraint templates - CONSTR-MET: - __ANY__: - - | - /* CONSTR-MET-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT * FROM [(${DOLLAR}{metricContext})] HAVING [(${DOLLAR}{metricContext})].metricValue [(${DOLLAR}{operator})] [(${DOLLAR}{threshold})] - - # Logical-Constraint templates - CONSTR-LOG: - __ANY__: - - | - /* CONSTR-LOG-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT 1 AS metricValue, 3 AS level, current_timestamp AS timestamp - FROM PATTERN [ EVERY ( [# th:each="con,iterStat : ${DOLLAR}{constraints}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{con} + ' '+${DOLLAR}{operator}+' ' : ${DOLLAR}{con}"] [/] ) ] - - # If-Then-Constraint templates - CONSTR-IF-THEN: - __ANY__: -#XXX: TEST: - - | - /* CONSTR-IF-THEN-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT 1 AS metricValue, 3 AS level, current_timestamp AS timestamp - FROM PATTERN [ EVERY ( [(${DOLLAR}{ifConstraint})] AND [(${DOLLAR}{thenConstraint})] [# th:if="${DOLLAR}{elseConstraint != null}" th:text="'OR NOT ( ' + ${DOLLAR}{ifConstraint} + ' ) AND ' + ${DOLLAR}{elseConstraint}"] [/] ) ] - - # Context templates - COMP-CTX: - __ANY__: - - | - /* COMP-CTX-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ [# th:switch="${DOLLAR}{selectMode}"] [# th:case="'epl'"] - SELECT [(${DOLLAR}{formula})] [/] [# th:case="*"] - SELECT EVAL( '[(${DOLLAR}{formula})]', '[# th:each="ctx,iterStat : ${DOLLAR}{components}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ',' : ${DOLLAR}{ctx}"] [/]', [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}"] [/] ) AS metricValue, - 3 AS level, - current_timestamp AS timestamp [/] [/] - FROM [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:utext="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx}+${DOLLAR}{windowClause}+' AS '+${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}+${DOLLAR}{windowClause}+' AS '+${DOLLAR}{ctx}"] [/] - [(${DOLLAR}{scheduleClause})] - - AGG-COMP-CTX: - __ANY__: - - | - /* COMP-CTX-AGG-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ [# th:switch="${DOLLAR}{selectMode}"] [# th:case="'epl'"] - SELECT [(${DOLLAR}{formula})] [/] [# th:case="*"] - SELECT EVALAGG( '[(${DOLLAR}{formula})]', '[# th:each="ctx,iterStat : ${DOLLAR}{components}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ',' : ${DOLLAR}{ctx}"] [/]', [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}"] [/] ) AS metricValue, - 3 AS level, - current_timestamp AS timestamp [/] [/] - FROM [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:utext="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx}+${DOLLAR}{windowClause}+' AS '+${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}+${DOLLAR}{windowClause}+' AS '+${DOLLAR}{ctx}"] [/] - [(${DOLLAR}{scheduleClause})] - - RAW-CTX: - PER_INSTANCE: - - | - /* RAW-CTX-PER_INSTANCE */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT * FROM [(${DOLLAR}{sensor})] [(${DOLLAR}{scheduleClause})] - - # Metric templates - TL-MET: - __ANY__: - - | - /* MET-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT * FROM [(${DOLLAR}{context})] - - # Metric Variable templates - VAR: - __ANY__: - - | - /* VAR-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ [# th:switch="${DOLLAR}{selectMode}"] [# th:case="'epl'"] - SELECT [(${DOLLAR}{formula})] [/] [# th:case="*"] - SELECT EVAL( '[(${DOLLAR}{formula})]', '[# th:each="ctx,iterStat : ${DOLLAR}{components}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ',' : ${DOLLAR}{ctx}"] [/]', [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}"] [/] ) AS metricValue, - 3 AS level, - current_timestamp AS timestamp [/] [/] - FROM [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx}+' AS '+${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}+' AS '+${DOLLAR}{ctx}"] [/] - - AGG-VAR: - __ANY__: - - | - /* VAR-AGG-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ [# th:switch="${DOLLAR}{selectMode}"] [# th:case="'epl'"] - SELECT [(${DOLLAR}{formula})] [/] [# th:case="*"] - SELECT EVALAGG( '[(${DOLLAR}{formula})]', '[# th:each="ctx,iterStat : ${DOLLAR}{components}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ',' : ${DOLLAR}{ctx}"] [/]', [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}"] [/] ) AS metricValue, - 3 AS level, - current_timestamp AS timestamp [/] [/] - FROM [# th:each="ctx,iterStat : ${DOLLAR}{contexts}" th:text="!${DOLLAR}{iterStat.last} ? ${DOLLAR}{ctx}+' AS '+${DOLLAR}{ctx} + ', ' : ${DOLLAR}{ctx}+' AS '+${DOLLAR}{ctx}"] [/] - - LOAD-VAR: - __ANY__: - - | - /* LOAD-VAR-any */ /*INSERT INTO [(${outputStream})]*/ - SELECT * FROM [(${context})] - - # Optimisation-Requirement templates - OPT-REQ-CTX: - __ANY__: - - | - /* OPT-REQ-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT * FROM [(${DOLLAR}{context})] - - OPT-REQ-VAR: - __ANY__: - - | - /* OPT-REQ-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT * FROM [(${DOLLAR}{variable})] - - # SLO templates - SLO: - __ANY__: - - | - /* SLO-any */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT * FROM [(${DOLLAR}{constraint})] - -#XXX:DEL:...remove next rule - XXX-extra-rule-templates: - BEP-AND: - GLOBAL: - - | - /* BEP-AND-GLOBAL : ALTERNATIVE */ /*INSERT INTO [(${DOLLAR}{outputStream})]*/ - SELECT le.* FROM PATTERN [ EVERY (le=[(${DOLLAR}{leftEvent})] AND re=[(${DOLLAR}{rightEvent})]) ] - RAW-CTX: - PER_INSTANCE: - - | - /* RAW-CTX-PER_INSTANCE */ - INSERT INTO TEST_STREAM - SELECT EVAL('-1*CPUMetric+CPUMetric_2+CPUMetric_3', '[(${DOLLAR}{metric})],[(${DOLLAR}{metric})]_2,[(${DOLLAR}{metric})]_3', [(${DOLLAR}{metric})], [(${DOLLAR}{metric})]_2, [(${DOLLAR}{metric})]_3) AS metricValue, - 1 AS level, - current_timestamp AS timestamp - FROM [(${DOLLAR}{metric})] as [(${DOLLAR}{metric})], [(${DOLLAR}{metric})] as [(${DOLLAR}{metric})]_2, [(${DOLLAR}{metric})] as [(${DOLLAR}{metric})]_3[(${DOLLAR}{scheduleClause})] - - FE: - PER_INSTANCE: - - | - /* XXX: TODO: FE-PER_INSTANCE */ - .......... Functional Event - CONSTR-IF-THEN: - PER_INSTANCE: - - | - /* XXX: TODO: CONSTR-IF-THEN-PER_INSTANCE */ - .......... If-Then constraint - CONSTR-VAR: - PER_INSTANCE: - - | - /* XXX: TODO: CONSTR-VAR-PER_INSTANCE */ - .......... Metric Variable constraint - CONSTR-LOG: - PER_INSTANCE: - - | - /* XXX: TODO: CONSTR-LOG-PER_INSTANCE */ - .......... Logical constraint - VAR: - PER_INSTANCE: - - | - /* XXX: TODO: VAR-PER_INSTANCE */ - .......... Metric Variable \ No newline at end of file diff --git a/nebulous/Dockerfile b/nebulous/Dockerfile new file mode 100644 index 0000000..4c8f7be --- /dev/null +++ b/nebulous/Dockerfile @@ -0,0 +1,16 @@ + +# ----------------- Builder image ----------------- +FROM docker.io/library/maven:3.9.6-eclipse-temurin-21 as builder +ENV BASEDIR /app +WORKDIR ${BASEDIR} +COPY ems-core ${BASEDIR}/ems-core +COPY ems-nebulous ${BASEDIR}/ems-nebulous +COPY pom.xml ${BASEDIR}/ +RUN mvn -f ${BASEDIR}/pom.xml -DskipTests clean install + +# ----------------- Runtime image ----------------- +FROM registry.gitlab.com/nebulous-project/ems-main/ems-server:2024-jan + +COPY --from=builder /app/ems-nebulous/target/ems-nebulous-plugin-1.0.0-SNAPSHOT-jar-with-dependencies.jar /plugins/ +ENV EXTRA_LOADER_PATHS=/plugins/* +ENV SCAN_PACKAGES=eu.nebulous.ems diff --git a/ems-core/.gitattributes b/nebulous/ems-core/.gitattributes similarity index 100% rename from ems-core/.gitattributes rename to nebulous/ems-core/.gitattributes diff --git a/ems-core/.gitignore b/nebulous/ems-core/.gitignore similarity index 100% rename from ems-core/.gitignore rename to nebulous/ems-core/.gitignore diff --git a/ems-core/README-for-TESTING.md b/nebulous/ems-core/README-for-TESTING.md similarity index 100% rename from ems-core/README-for-TESTING.md rename to nebulous/ems-core/README-for-TESTING.md diff --git a/ems-core/baguette-client-install/pom.xml b/nebulous/ems-core/baguette-client-install/pom.xml similarity index 100% rename from ems-core/baguette-client-install/pom.xml rename to nebulous/ems-core/baguette-client-install/pom.xml diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationProperties.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationProperties.java similarity index 97% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationProperties.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationProperties.java index 69bd44d..703232a 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationProperties.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationProperties.java @@ -41,6 +41,8 @@ public class ClientInstallationProperties implements InitializingBean { private String clientInstallationRequestsTopic = "ems.client.installation.requests"; private String clientInstallationReportsTopic = "ems.client.installation.reports"; private List clientInstallationReportNodeInfoPatterns = new ArrayList<>(); + private String clientInfoRequestsTopic = "ems.client.info.requests"; + private String clientInfoReportsTopic = "ems.client.info.reports"; private String baseDir; // EMS client home directory private String rootCmd; // Root command (e.g. 'sudo', or 'echo ${NODE_SSH_PASSWORD} | sudo -S ') diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationRequestListener.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationRequestListener.java similarity index 55% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationRequestListener.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationRequestListener.java index b8399ea..a654938 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationRequestListener.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationRequestListener.java @@ -29,11 +29,13 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Service; -import javax.jms.*; +import jakarta.jms.*; import java.time.Instant; import java.util.*; import java.util.stream.Collectors; +import static gr.iccs.imu.ems.baguette.client.install.ClientInstallationTask.TASK_TYPE; + /** * Installation Event Listener */ @@ -93,54 +95,92 @@ public class ClientInstallationRequestListener implements InitializingBean { ? connectionFactory.createConnection(brokerCepService.getBrokerUsername(), brokerCepService.getBrokerPassword()) : connectionFactory.createConnection()); Session session = connection.createSession(true, 0); - MessageConsumer consumer = session.createConsumer( - new ActiveMQTopic(properties.getClientInstallationRequestsTopic())); - consumer.setMessageListener(getMessageListener()); + + List topics = Arrays.asList( + properties.getClientInstallationRequestsTopic(), + properties.getClientInfoRequestsTopic() + ); + log.debug("InstallationEventListener: Will subscribe to topics: {}", topics); + + MessageListener listener = getMessageListener(); + for (String topic : topics) { + MessageConsumer consumer = session.createConsumer( + new ActiveMQTopic( topic )); + consumer.setMessageListener(listener); + log.debug("InstallationEventListener: Subscribed to topic: {}", topic); + } + connection.start(); log.debug("InstallationEventListener: STARTED"); } private MessageListener getMessageListener() { return message -> { - String requestId = null; + Map request = null; + TASK_TYPE requestType = TASK_TYPE.OTHER; try { // Extract request from JMS message - Map request = extractRequest(message); + request = extractRequest(message); log.debug("InstallationEventListener: Got a client installation request: {}", request); - if (request==null) - throw new IllegalArgumentException("Could not extract request data"); - requestId = request.get("requestId").trim(); + if (request==null) { + clientInstaller.sendErrorClientInstallationReport(TASK_TYPE.OTHER, + null, "ERROR: Invalid request. Could not extract request data"); + return; + } - // Check incoming request - List errors = new ArrayList<>(); - if (StringUtils.isBlank(request.get("requestId"))) errors.add("requestId"); - if (StringUtils.isBlank(request.get("requestType"))) errors.add("requestType"); - if (StringUtils.isBlank(request.get("deviceOs"))) errors.add("deviceOs"); - if (StringUtils.isBlank(request.get("deviceIpAddress"))) errors.add("deviceIpAddress"); - if (StringUtils.isBlank(request.get("deviceUsername"))) errors.add("deviceUsername"); - if (StringUtils.isBlank(request.get("devicePassword")) && StringUtils.isBlank(request.get("devicePublicKey"))) - errors.add("Both devicePublicKey and devicePublicKey"); - if (! errors.isEmpty()) { - String errorMessage = "Missing fields: " + String.join(", ", errors); - throw new IllegalArgumentException(errorMessage); + // Get request type + String requestTypeStr = request.get("requestType"); + if (StringUtils.isBlank(requestTypeStr)) { + clientInstaller.sendErrorClientInstallationReport(TASK_TYPE.OTHER, + request, "ERROR: Invalid request. Missing requestType field"); + return; + } + try { + if ("VM".equalsIgnoreCase(requestTypeStr)) requestTypeStr = TASK_TYPE.INSTALL.name(); + if ("REMOVE".equalsIgnoreCase(requestTypeStr)) requestTypeStr = TASK_TYPE.UNINSTALL.name(); + if ("UPDATE".equalsIgnoreCase(requestTypeStr)) requestTypeStr = TASK_TYPE.INFO.name(); + requestType = TASK_TYPE.valueOf(requestTypeStr.trim().toUpperCase()); + } catch (Exception e) { + clientInstaller.sendErrorClientInstallationReport(TASK_TYPE.OTHER, + request, "ERROR: Invalid request. Invalid requestType field value: "+requestTypeStr); + return; + } + + // If not an INFO or NODE_DETAILS request run extra checks + if (TASK_TYPE.INFO != requestType && TASK_TYPE.NODE_DETAILS != requestType) { + // Check incoming request + List errors = new ArrayList<>(); + if (StringUtils.isBlank(request.get("requestId")) && + (TASK_TYPE.DIAGNOSTICS==requestType || TASK_TYPE.INSTALL==requestType)) + errors.add("requestId"); + if (StringUtils.isBlank(request.get("deviceOs"))) errors.add("deviceOs"); + if (StringUtils.isBlank(request.get("deviceIpAddress"))) errors.add("deviceIpAddress"); + if (StringUtils.isBlank(request.get("deviceUsername"))) errors.add("deviceUsername"); + if (StringUtils.isBlank(request.get("devicePassword")) + && StringUtils.isBlank(request.get("devicePublicKey"))) errors.add("Both devicePublicKey and devicePublicKey"); + if (!errors.isEmpty()) { + String errorMessage = "Missing fields: " + String.join(", ", errors); + clientInstaller.sendErrorClientInstallationReport(requestType, request, "ERROR: "+errorMessage); + return; + } } // Process request based on its type - String requestType = request.get("requestType").trim(); switch (requestType) { - case "DIAGNOSTICS" -> processDiagnosticsRequest(request); - case "VM" -> processOnboardingRequest(request); - case "REMOVE" -> processRemoveRequest(request); + case DIAGNOSTICS -> processDiagnosticsRequest(request); + case INSTALL -> processOnboardingRequest(request); + case REINSTALL -> processReinstallRequest(request); + case UNINSTALL -> processRemoveRequest(request); + case NODE_DETAILS -> processNodeDetailsRequest(request); + case INFO -> processInfoRequest(request); default -> throw new IllegalArgumentException("Unsupported request type: "+requestType); }; } catch (Throwable e) { log.error("InstallationEventListener: ERROR: ", e); try { - if (StringUtils.isNotBlank(requestId)) - clientInstaller.sendErrorClientInstallationReport(requestId, "ERROR: "+e.getMessage()); - else - clientInstaller.sendErrorClientInstallationReport("UNKNOWN-REQUEST-ID", "ERROR: "+e.getMessage()+"\n"+message); + clientInstaller.sendErrorClientInstallationReport( + requestType, request, "ERROR: "+e.getMessage()+"\n"+message); } catch (Throwable t) { log.info("InstallationEventListener: EXCEPTION while sending Client installation report for incoming request: request={}, Exception: ", message, t); } @@ -175,7 +215,7 @@ public class ClientInstallationRequestListener implements InitializingBean { // Create client installation task ClientInstallationTask newTask = ClientInstallationTask.builder() .id(request.get("requestId")) - .taskType(ClientInstallationTask.TASK_TYPE.DIAGNOSTIC) + .taskType(ClientInstallationTask.TASK_TYPE.DIAGNOSTICS) .requestId(request.get("requestId")) .type(request.get("requestType")) .nodeId(request.get("deviceId")) @@ -214,7 +254,8 @@ public class ClientInstallationRequestListener implements InitializingBean { String requestId = request.getOrDefault("requestId", "").trim(); log.info("InstallationEventListener: New node ONBOARDING request with Id: {}", requestId); if (StringUtils.isBlank(requestId)) { - clientInstaller.sendErrorClientInstallationReport("MISSING-REQUEST-ID", "INVALID REQUEST. MISSING REQUEST ID"); + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.INSTALL, request, "INVALID REQUEST. MISSING REQUEST ID"); return; } @@ -223,14 +264,132 @@ public class ClientInstallationRequestListener implements InitializingBean { nodeRegistration.registerNode(null, convertToNodeInfoMap(request), new TranslationContext(requestId)); } catch (Exception e) { log.warn("InstallationEventListener: EXCEPTION while executing ONBOARDING request with Id: {}\n", requestId, e); - clientInstaller.sendErrorClientInstallationReport(requestId, "ERROR: "+e.getMessage()); + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.INSTALL, request, "ERROR: "+e.getMessage()); + } + } + + private void processReinstallRequest(Map request) throws Exception { + String requestId = request.getOrDefault("requestId", "").trim(); + String deviceId = request.getOrDefault("deviceId", "").trim(); + String ipAddress = request.getOrDefault("deviceIpAddress", "").trim(); + log.info("InstallationEventListener: REINSTALL request with device Id: {}, ip-address={}", deviceId, ipAddress); + if (StringUtils.isBlank(deviceId)) { + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.REINSTALL, request, "INVALID REQUEST. MISSING DEVICE ID"); + return; + } + if (StringUtils.isBlank(ipAddress)) { + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.REINSTALL, request, "INVALID REQUEST. MISSING DEVICE IP ADDRESS"); + return; + } + + try { + log.debug("InstallationEventListener: Reinstalling node due to REINSTALL request with Id: {}", deviceId); + nodeRegistration.reinstallNode(ipAddress, new TranslationContext(requestId)); + } catch (Exception e) { + log.warn("InstallationEventListener: EXCEPTION while executing REINSTALL request with Id: {}\n", deviceId, e); + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.REINSTALL, request, "ERROR: "+e.getMessage()); + } + } + + private void processRemoveRequest(Map request) throws Exception { + String requestId = request.getOrDefault("requestId", "").trim(); + String deviceId = request.getOrDefault("deviceId", "").trim(); + String nodeAddress = request.getOrDefault("deviceIpAddress", "").trim(); + log.info("InstallationEventListener: New node REMOVE request with Id: {}, address={}", deviceId, nodeAddress); + if (StringUtils.isBlank(deviceId)) { + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.UNINSTALL, request, "INVALID REQUEST. MISSING DEVICE ID"); + return; + } + if (StringUtils.isBlank(nodeAddress)) { + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.UNINSTALL, request, "INVALID REQUEST. MISSING IP ADDRESS"); + return; + } + + try { + log.debug("InstallationEventListener: Off-boarding node due to REMOVE request with Id: {}, requestId={}", deviceId, requestId); + nodeRegistration.unregisterNode(nodeAddress, new TranslationContext(requestId)); + } catch (Exception e) { + log.warn("InstallationEventListener: EXCEPTION while executing REMOVE request with Id: {}\n", deviceId, e); + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.UNINSTALL, request, "ERROR: "+e.getMessage()); + } + } + + private void processNodeDetailsRequest(Map request) throws Exception { + String nodeAddress = request.getOrDefault("deviceIpAddress", "").trim(); + log.info("InstallationEventListener: New node NODE_DETAILS request with: address={}", nodeAddress); + if (StringUtils.isBlank(nodeAddress)) { + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.NODE_DETAILS, request, "INVALID REQUEST. MISSING IP ADDRESS"); + return; + } + + log.info("InstallationEventListener: Processing NODE_DETAILS request"); + try { + log.debug("InstallationEventListener: Requesting NODE_DETAILS"); + NodeRegistryEntry entry = nodeRegistration.requestNodeDetails(nodeAddress); + log.trace("InstallationEventListener: NODE_DETAILS: entry={}", entry); + + if (entry!=null) { + // Get node details from NodeRegistry + Map response = clientInstaller.createReportEventFromNodeData( + -1, TASK_TYPE.NODE_DETAILS, "", "", + entry.getIpAddress(), entry.getReference(), entry.getPreregistration(), "SUCCESS"); + log.debug("InstallationEventListener: NODE_DETAILS response (1): {}", response); + + // ...make response map mutable + response = new LinkedHashMap<>(response); + + // ...include additional fields + Map preregData = entry.getPreregistration(); + response.put("os", preregData.getOrDefault("NODE_OPERATINGSYSTEM", "")); + response.put("name", preregData.getOrDefault("NODE_NAME", "")); + response.put("username", preregData.getOrDefault("NODE_SSH_USERNAME", "")); + response.put("password", preregData.getOrDefault("NODE_SSH_PASSWORD", "")); + response.put("key", preregData.getOrDefault("NODE_SSH_KEY", "")); + + response.put("requestId", ""); + response.put("state", entry.getState()!=null ? entry.getState().name() : ""); + log.debug("InstallationEventListener: NODE_DETAILS response (2): {}", response); + + // Send NODE_DETAILS response + log.trace("InstallationEventListener: Sending NODE_DETAILS response: {}", response); + clientInstaller.publishReport(new LinkedHashMap<>(response)); + + log.debug("InstallationEventListener: Sent NODE_DETAILS response: {}", response); + } else { + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.NODE_DETAILS, request, "ERROR: No node found in NodeRegistry with IP address: "+nodeAddress); + } + } catch (Exception e) { + log.warn("InstallationEventListener: EXCEPTION while retrieving NODE_DETAILS:\n", e); + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.INFO, request, "ERROR: "+e.getMessage()); + } + } + + private void processInfoRequest(Map request) throws Exception { + log.info("InstallationEventListener: INFO request"); + try { + log.debug("InstallationEventListener: Requesting INFO"); + nodeRegistration.requestInfo(); + } catch (Exception e) { + log.warn("InstallationEventListener: EXCEPTION while executing INFO:\n", e); + clientInstaller.sendErrorClientInstallationReport( + TASK_TYPE.INFO, request, "ERROR: "+e.getMessage()); } } private Map convertToNodeInfoMap(Map request) { log.trace("InstallationEventListener.convertToNodeInfoMap(): BEGIN: request: {}", request); String requestId = request.get("requestId"); - String nodeId = request.get("requestId"); + String nodeId = request.get("deviceId"); String nodeOs = request.get("deviceOs"); String nodeAddress = request.get("deviceIpAddress"); String nodeType = request.get("deviceType"); @@ -267,26 +426,4 @@ public class ClientInstallationRequestListener implements InitializingBean { log.trace("InstallationEventListener.convertToNodeInfoMap(): END: nodeMap: {}", nodeMap); return nodeMap; } - - private void processRemoveRequest(Map request) throws Exception { - String requestId = request.getOrDefault("requestId", "").trim(); - String nodeAddress = request.getOrDefault("deviceIpAddress", "").trim(); - log.info("InstallationEventListener: New node REMOVE request with Id: {}, address={}", requestId, nodeAddress); - if (StringUtils.isBlank(requestId)) { - clientInstaller.sendErrorClientInstallationReport("MISSING-REQUEST-ID", "INVALID REQUEST. MISSING REQUEST ID"); - return; - } - if (StringUtils.isBlank(nodeAddress)) { - clientInstaller.sendErrorClientInstallationReport(requestId, "INVALID REQUEST. MISSING IP ADDRESS"); - return; - } - - try { - log.debug("InstallationEventListener: Off-boarding node due to REMOVE request with Id: {}", requestId); - nodeRegistration.unregisterNode(nodeAddress, new TranslationContext(requestId)); - } catch (Exception e) { - log.warn("InstallationEventListener: EXCEPTION while executing REMOVE request with Id: {}\n", requestId, e); - clientInstaller.sendErrorClientInstallationReport(requestId, "ERROR: "+e.getMessage()); - } - } } diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationTask.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationTask.java similarity index 92% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationTask.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationTask.java index cfee0bc..7392a7c 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationTask.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallationTask.java @@ -24,7 +24,7 @@ import java.util.concurrent.Callable; @Data @Builder public class ClientInstallationTask { - public enum TASK_TYPE { INSTALL, UNINSTALL, DIAGNOSTIC, OTHER } + public enum TASK_TYPE { INSTALL, REINSTALL, UNINSTALL, NODE_DETAILS, INFO, DIAGNOSTICS, OTHER } private final String id; private final TASK_TYPE taskType; @@ -39,6 +39,7 @@ public class ClientInstallationTask { private final NodeRegistryEntry nodeRegistryEntry; private final List instructionSets; private final TranslationContext translationContext; + @Builder.Default private boolean nodeMustBeInRegistry = true; private Callable callback; diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstaller.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstaller.java similarity index 79% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstaller.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstaller.java index bd20ce2..9b3a931 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstaller.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstaller.java @@ -22,8 +22,9 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import javax.jms.JMSException; -import javax.validation.constraints.NotNull; +import jakarta.jms.JMSException; +import jakarta.validation.constraints.NotNull; +import java.io.Serializable; import java.time.Instant; import java.util.Collections; import java.util.LinkedHashMap; @@ -33,6 +34,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; +import static gr.iccs.imu.ems.baguette.client.install.ClientInstallationTask.TASK_TYPE; + /** * Client installer */ @@ -128,7 +131,7 @@ public class ClientInstaller implements InitializingBean { return executeVmOrBaremetalTask(task, taskCounter); } else //if ("DIAGNOSTICS".equalsIgnoreCase(task.getType())) { - if (task.getTaskType()==ClientInstallationTask.TASK_TYPE.DIAGNOSTIC) { + if (task.getTaskType()==TASK_TYPE.DIAGNOSTICS) { return executeDiagnosticsTask(task, taskCounter); } else { log.error("ClientInstaller: UNSUPPORTED TASK TYPE: {}", task.getType()); @@ -181,13 +184,13 @@ public class ClientInstaller implements InitializingBean { } // Pre-register Node to baguette Server Coordinator - if (task.getTaskType()==ClientInstallationTask.TASK_TYPE.INSTALL) { + if (task.getTaskType()==TASK_TYPE.INSTALL) { log.debug("ClientInstaller: POST-INSTALLATION: Node is being pre-registered: {}", entry); baguetteServer.getNodeRegistry().getCoordinator().preregister(entry); } // Un-register Node from baguette Server Coordinator - if (task.getTaskType()==ClientInstallationTask.TASK_TYPE.UNINSTALL) { + if (task.getTaskType()==TASK_TYPE.UNINSTALL) { ClientShellCommand csc = ClientShellCommand.getActiveByIpAddress(entry.getIpAddress()); log.debug("ClientInstaller: POST-INSTALLATION: CSC of node to be unregistered: {}", csc); if (csc!=null) { @@ -247,43 +250,89 @@ public class ClientInstaller implements InitializingBean { createReportEventFromExecutionResults(taskCnt, task, resultStr)); log.info("ClientInstaller: Sending SUCCESS execution report for Task #{}: destination={}, report={}", taskCnt, properties.getClientInstallationReportsTopic(), executionReport); - brokerCepService.publishSerializable( - null, properties.getClientInstallationReportsTopic(), executionReport, true); + publishReport(executionReport); } - public void sendErrorClientInstallationReport(String requestId, String resultStr) throws JMSException { - log.trace("ClientInstaller: Preparing ERROR execution report event for request: result={}, requestId={}", resultStr, requestId); + public void sendErrorClientInstallationReport(@NonNull TASK_TYPE requestType, Map request, String resultStr) throws JMSException { + sendErrorClientInstallationReport(requestType, request, null, resultStr); + } + + public void sendErrorClientInstallationReport(@NonNull TASK_TYPE requestType, Map request, String reference, String resultStr) throws JMSException { + log.trace("ClientInstaller: Preparing ERROR execution report event for request: result={}, request={}", resultStr, request); + String requestId = getOrDefault(request, "requestId", "MISSING-REQUEST-ID"); + String deviceId = getOrDefault(request, "deviceId", "MISSING-DEVICE-ID"); + String ipAddress = getOrDefault(request, "deviceIpAddress", "MISSING-DEVICE-ADDRESS"); LinkedHashMap executionReport = new LinkedHashMap<>( - createReportEvent(requestId, null, resultStr, Collections.emptyMap())); - log.info("ClientInstaller: Sending ERROR execution report for request: destination={}, report={}", + createReportEvent(requestType, + requestId, deviceId, ipAddress, reference, resultStr, Collections.emptyMap())); + log.info("ClientInstaller: Sending ERROR execution report: destination={}, report={}", properties.getClientInstallationReportsTopic(), executionReport); + publishReport(executionReport); + } + + private String getOrDefault(Map map, String key, String defaultValue) { + if (map==null) return defaultValue; + return map.getOrDefault(key, defaultValue); + } + + public void publishReport(Serializable report) throws JMSException { brokerCepService.publishSerializable( - null, properties.getClientInstallationReportsTopic(), executionReport, true); + null, properties.getClientInstallationReportsTopic(), report, true); } private Map createReportEventFromExecutionResults(long taskCnt, @NonNull ClientInstallationTask task, String resultStr) { + log.trace("ClientInstaller: createReportEventFromExecutionResults: Task #{}: ARGS: result={}, task={}", taskCnt, resultStr, task); + + // Get execution results Map data = task.getNodeRegistryEntry().getPreregistration(); log.trace("ClientInstaller: createReportEventFromExecutionResults: Task #{}: Execution data:\n{}", taskCnt, data); + + // Create report event + TASK_TYPE requestType = task.getTaskType(); + String requestId = task.getRequestId(); + String deviceId = task.getNodeId(); + return createReportEventFromNodeData(taskCnt, requestType, requestId, deviceId, + task.getAddress(), task.getNodeRegistryEntry().getReference(), data, resultStr); + } + + public Map createReportEventFromNodeData(long taskCnt, + TASK_TYPE requestType, + String requestId, + String deviceId, + String ipAddress, + String reference, + Map data, + String resultStr) + { + // Copy node info from execution results Map nodeInfoMap = new LinkedHashMap<>(); properties.getClientInstallationReportNodeInfoPatterns().forEach(pattern -> { - log.trace("ClientInstaller: createReportEventFromExecutionResults: Task #{}:Applying pattern: {}", taskCnt, pattern); + log.trace("ClientInstaller: createReportEventFromNodeData: Task #{}: Applying pattern: {}", taskCnt, pattern); data.keySet().stream() //.peek(key->log.trace(" ----> Checking: key={}, match={}", key, pattern.matcher(key).matches())) .filter(key -> pattern.matcher(key).matches()) .forEach(key -> nodeInfoMap.put(key, data.get(key))); }); - log.debug("ClientInstaller: createReportEventFromExecutionResults: Task #{}: Node info collected: {}", taskCnt, nodeInfoMap); - String requestId = StringUtils.defaultIfBlank(task.getRequestId(), task.getId()); - return createReportEvent(requestId, task.getNodeRegistryEntry().getReference(), resultStr, nodeInfoMap); + log.debug("ClientInstaller: createReportEventFromNodeData: Task #{}: Node info collected: {}", taskCnt, nodeInfoMap); + + // Create and send report event + return createReportEvent( + requestType, requestId, deviceId, ipAddress, reference, resultStr, nodeInfoMap); } - private static Map createReportEvent(@NonNull String requestId, + private static Map createReportEvent(@NonNull TASK_TYPE requestType, + String requestId, + String deviceId, + String ipAddress, String reference, @NonNull String statusStr, Map nodeInfoMap) { return Map.of( - "requestId", requestId, + "requestType", requestType.name(), + "requestId", Objects.requireNonNullElse(requestId, ""), + "deviceId", Objects.requireNonNullElse(deviceId, ""), + "deviceIpAddress", Objects.requireNonNullElse(ipAddress, ""), "reference", Objects.requireNonNullElse(reference, ""), "status", statusStr, "nodeInfo", nodeInfoMap!=null ? nodeInfoMap : Collections.emptyMap(), diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallerPlugin.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallerPlugin.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallerPlugin.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/ClientInstallerPlugin.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/InstallationContextProcessorPlugin.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/InstallationContextProcessorPlugin.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/InstallationContextProcessorPlugin.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/InstallationContextProcessorPlugin.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshClientInstaller.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshClientInstaller.java similarity index 98% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshClientInstaller.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshClientInstaller.java index c019c72..b066c18 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshClientInstaller.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshClientInstaller.java @@ -408,7 +408,7 @@ public class SshClientInstaller implements ClientInstallerPlugin { setChannelStreams(channel); log.debug("SshClientInstaller: task #{}: EXEC: New channel id: {}", taskCounter, channel.getChannelId()); //streamLogger.getInvertedIn().write(command.getBytes()); - streamLogger.logMessage(String.format("EXEC: %s\n", command)); + streamLogger.logMessage("EXEC: %s\n".formatted(command)); try { // Sending command to remote side log.debug("SshClientInstaller: task #{}: EXEC: Sending command for execution: {} (connect timeout: {}ms)", taskCounter, command, connectTimeout); @@ -444,7 +444,7 @@ public class SshClientInstaller implements ClientInstallerPlugin { return true; } - streamLogger.logMessage(String.format("DOWNLOAD: SCP: %s -> %s\n", remoteFilePath, localFilePath)); + streamLogger.logMessage("DOWNLOAD: SCP: %s -> %s\n".formatted(remoteFilePath, localFilePath)); try { log.info("SshClientInstaller: Downloading file: task #{}: remote: {} -> local: {}", taskCounter, remoteFilePath, localFilePath); ScpClientCreator creator = new DefaultScpClientCreator(); @@ -465,7 +465,7 @@ public class SshClientInstaller implements ClientInstallerPlugin { return true; } - streamLogger.logMessage(String.format("UPLOAD: SCP: %s -> %s\n", localFilePath, remoteFilePath)); + streamLogger.logMessage("UPLOAD: SCP: %s -> %s\n".formatted(localFilePath, remoteFilePath)); try { long startTm = System.currentTimeMillis(); log.info("SshClientInstaller: Uploading file: task #{}: local: {} -> remote: {}", taskCounter, localFilePath, remoteFilePath); @@ -488,7 +488,7 @@ public class SshClientInstaller implements ClientInstallerPlugin { return true; } - streamLogger.logMessage(String.format("WRITE FILE: SCP: %s, content-length=%d \n", remoteFilePath, content.length())); + streamLogger.logMessage("WRITE FILE: SCP: %s, content-length=%d \n".formatted(remoteFilePath, content.length())); try { long timestamp = System.currentTimeMillis(); /*Collection permissions = isExecutable @@ -819,7 +819,7 @@ public class SshClientInstaller implements ClientInstallerPlugin { contents = StringSubstitutor.replace(contents, valueMap); log.trace("SshClientInstaller: Task #{}: FILE: {}, final-content:\n{}", taskCounter, targetFile, contents); - String description = String.format("Copy file from server to temp to client: %s -> %s", sourcePath.toString(), targetFile); + String description = "Copy file from server to temp to client: %s -> %s".formatted(sourcePath.toString(), targetFile); return sshFileWrite(contents, targetFile, isExecutable); } diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshConfig.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshConfig.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshConfig.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshConfig.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshJsClientInstaller.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshJsClientInstaller.java similarity index 99% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshJsClientInstaller.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshJsClientInstaller.java index ddc2722..80fb38f 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshJsClientInstaller.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/SshJsClientInstaller.java @@ -156,8 +156,7 @@ public class SshJsClientInstaller extends SshClientInstaller { log.error("SshJsClientInstaller: Task #{}: JS installation script returned NULL: {}", getTaskCounter(), jsScript); return INSTRUCTION_RESULT.FAIL; } - if (result instanceof Integer) { - int code = (int)result; + if (result instanceof Integer code) { log.info("SshJsClientInstaller: Task #{}: JS installation script returned: code={}, script: {}", getTaskCounter(), code, jsScript); return code==0 ? INSTRUCTION_RESULT.SUCCESS : INSTRUCTION_RESULT.FAIL; } else { diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/StreamLogger.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/StreamLogger.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/StreamLogger.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/StreamLogger.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/api/INodeRegistration.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/api/INodeRegistration.java similarity index 74% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/api/INodeRegistration.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/api/INodeRegistration.java index b70d2e4..f4bc341 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/api/INodeRegistration.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/api/INodeRegistration.java @@ -9,6 +9,7 @@ package gr.iccs.imu.ems.baguette.client.install.api; +import gr.iccs.imu.ems.baguette.server.NodeRegistryEntry; import gr.iccs.imu.ems.translate.TranslationContext; import java.util.Map; @@ -16,4 +17,7 @@ import java.util.Map; public interface INodeRegistration { String registerNode(String baseUrl, Map nodeInfo, TranslationContext translationContext) throws Exception; String unregisterNode(String nodeAddress, TranslationContext translationContext) throws Exception; + String reinstallNode(String ipAddress, TranslationContext translationContext) throws Exception; + NodeRegistryEntry requestNodeDetails(String nodeAddress) throws Exception; + void requestInfo() throws Exception; } diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/AbstractInstallationHelper.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/AbstractInstallationHelper.java similarity index 99% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/AbstractInstallationHelper.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/AbstractInstallationHelper.java index d0936ad..e4711ee 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/AbstractInstallationHelper.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/AbstractInstallationHelper.java @@ -281,7 +281,8 @@ public abstract class AbstractInstallationHelper implements InitializingBean, Ap contents = StringSubstitutor.replace(contents, valueMap); String tmpFile = clientTmpDir+"/installEMS_"+System.currentTimeMillis(); instructionsSet - .appendLog(String.format("Copy file from server to temp to client: %s -> %s -> %s", p.toString(), tmpFile, targetFile)); + .appendLog("Copy file from server to temp to client: %s -> %s -> %s" + .formatted(p.toString(), tmpFile, targetFile)); return _appendCopyInstructions(instructionsSet, targetFile, tmpFile, contents, clientTmpDir); } diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelper.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelper.java similarity index 93% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelper.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelper.java index 8f4a868..c8a9b4e 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelper.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelper.java @@ -33,5 +33,6 @@ public interface InstallationHelper { return createClientInstallationTask(entry, null); } ClientInstallationTask createClientInstallationTask(NodeRegistryEntry entry, TranslationContext translationContext) throws Exception; + ClientInstallationTask createClientReinstallTask(NodeRegistryEntry entry, TranslationContext translationContext) throws Exception; ClientInstallationTask createClientUninstallTask(NodeRegistryEntry entry, TranslationContext translationContext) throws Exception; } diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelperFactory.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelperFactory.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelperFactory.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/InstallationHelperFactory.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/VmInstallationHelper.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/VmInstallationHelper.java similarity index 97% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/VmInstallationHelper.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/VmInstallationHelper.java index 4857738..dae0db0 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/VmInstallationHelper.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/helper/VmInstallationHelper.java @@ -68,6 +68,15 @@ public class VmInstallationHelper extends AbstractInstallationHelper { return createClientTask(ClientInstallationTask.TASK_TYPE.INSTALL, entry, translationContext, instructionsSetList); } + @Override + public ClientInstallationTask createClientReinstallTask(NodeRegistryEntry entry, TranslationContext translationContext) throws IOException { + // Get EMS client reinstall instructions for VM node + List instructionsSetList = + prepareInstallationInstructionsForOs(entry); + + return createClientTask(ClientInstallationTask.TASK_TYPE.REINSTALL, entry, translationContext, instructionsSetList); + } + @Override public ClientInstallationTask createClientUninstallTask(NodeRegistryEntry entry, TranslationContext translationContext) throws Exception { // Clear any cached 'instruction-files' override (from a previous run) @@ -358,7 +367,7 @@ public class VmInstallationHelper extends AbstractInstallationHelper { targetFile = remoteTargetDir + targetFile; String contents = new String(Files.readAllBytes(path)); contents = StringSubstitutor.replace(contents, valueMap); - String description = String.format("Copy file from server to temp to client: %s -> %s", path.toString(), targetFile); + String description = "Copy file from server to temp to client: %s -> %s".formatted(path.toString(), targetFile); return _appendCopyInstructions(instructionsSet, targetFile, description, contents); } diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/AbstractInstructionsBase.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/AbstractInstructionsBase.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/AbstractInstructionsBase.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/AbstractInstructionsBase.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_RESULT.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_RESULT.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_RESULT.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_RESULT.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_TYPE.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_TYPE.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_TYPE.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/INSTRUCTION_TYPE.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/Instruction.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/Instruction.java similarity index 98% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/Instruction.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/Instruction.java index 0645255..f384d43 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/Instruction.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/Instruction.java @@ -13,7 +13,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; import lombok.experimental.Accessors; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import java.util.Map; import java.util.regex.Pattern; diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsService.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsService.java similarity index 98% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsService.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsService.java index 23d64ae..16fce77 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsService.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsService.java @@ -59,8 +59,8 @@ public class InstructionsService implements EnvironmentAware { log.trace("InstructionsService: checkCondition: Expression result: {}", result); if (result==null) throw new IllegalArgumentException("Condition evaluation returned null: " + condition); - if (result instanceof Boolean) - return (Boolean)result; + if (result instanceof Boolean booleanValue) + return booleanValue; throw new IllegalArgumentException("Condition evaluation returned a non-boolean value: " + result + ", condition: " + condition+", resolved condition: "+ conditionResolved); } diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsSet.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsSet.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsSet.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/instruction/InstructionsSet.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/AllowedTopicsProcessorPlugin.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/AllowedTopicsProcessorPlugin.java similarity index 89% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/AllowedTopicsProcessorPlugin.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/AllowedTopicsProcessorPlugin.java index b7d3862..c82f9d7 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/AllowedTopicsProcessorPlugin.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/AllowedTopicsProcessorPlugin.java @@ -52,22 +52,15 @@ public class AllowedTopicsProcessorPlugin implements InstallationContextProcesso addedTopicsSet.add(metricName); } - // Get sensor configuration (as a list of KeyValuePair's) - Map sensorConfig = null; - if (monitor.getSensor().isPullSensor()) { - // Pull Sensor - sensorConfig = monitor.getSensor().pullSensor().getConfiguration(); - } else { - // Push Sensor - sensorConfig = monitor.getSensor().pushSensor().getAdditionalProperties(); - } + // Get sensor configuration + Map sensorConfig = monitor.getSensor().getConfiguration();; // Process Destination aliases, if specified in configuration if (sensorConfig!=null) { String k = sensorConfig.keySet().stream() .filter(key -> StrUtil.compareNormalized(key, EmsConstant.COLLECTOR_DESTINATION_ALIASES)) .findAny().orElse(null); - String aliases = (k!=null) ? sensorConfig.get(k) : null; + String aliases = (k!=null && sensorConfig.get(k) instanceof String) ? sensorConfig.get(k).toString() : null; if (StringUtils.isNotBlank(aliases)) { for (String alias : aliases.trim().split(EmsConstant.COLLECTOR_DESTINATION_ALIASES_DELIMITERS)) { diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/PrometheusProcessorPlugin.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/PrometheusProcessorPlugin.java similarity index 98% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/PrometheusProcessorPlugin.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/PrometheusProcessorPlugin.java index 49aac28..1fe58d4 100644 --- a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/PrometheusProcessorPlugin.java +++ b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/install/plugin/PrometheusProcessorPlugin.java @@ -62,7 +62,8 @@ public class PrometheusProcessorPlugin implements InstallationContextProcessorPl log.trace("PrometheusProcessorPlugin: Task #{}: MONITOR: component={}, metric={}", taskCounter, componentName, metricName); if (monitor.getSensor().isPullSensor()) { if (monitor.getSensor().pullSensor().getConfiguration()!=null) { - Map config = monitor.getSensor().pullSensor().getConfiguration(); + Map config = StrUtil.deepFlattenMap( + monitor.getSensor().getConfiguration()); log.trace("PrometheusProcessorPlugin: Task #{}: MONITOR with PULL SENSOR: config: {}", taskCounter, config); // Get Prometheus related settings diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ClientRecoveryPlugin.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ClientRecoveryPlugin.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ClientRecoveryPlugin.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ClientRecoveryPlugin.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/SelfHealingManagerImpl.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/SelfHealingManagerImpl.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/SelfHealingManagerImpl.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/SelfHealingManagerImpl.java diff --git a/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ServerSelfHealingProperties.java b/nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ServerSelfHealingProperties.java similarity index 100% rename from ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ServerSelfHealingProperties.java rename to nebulous/ems-core/baguette-client-install/src/main/java/gr/iccs/imu/ems/baguette/client/selfhealing/ServerSelfHealingProperties.java diff --git a/ems-core/baguette-client/LICENSE b/nebulous/ems-core/baguette-client/LICENSE similarity index 100% rename from ems-core/baguette-client/LICENSE rename to nebulous/ems-core/baguette-client/LICENSE diff --git a/ems-core/baguette-client/bin/baguette-client b/nebulous/ems-core/baguette-client/bin/baguette-client similarity index 100% rename from ems-core/baguette-client/bin/baguette-client rename to nebulous/ems-core/baguette-client/bin/baguette-client diff --git a/ems-core/baguette-client/bin/client.sh b/nebulous/ems-core/baguette-client/bin/client.sh similarity index 100% rename from ems-core/baguette-client/bin/client.sh rename to nebulous/ems-core/baguette-client/bin/client.sh diff --git a/ems-core/baguette-client/bin/install.sh b/nebulous/ems-core/baguette-client/bin/install.sh similarity index 100% rename from ems-core/baguette-client/bin/install.sh rename to nebulous/ems-core/baguette-client/bin/install.sh diff --git a/ems-core/baguette-client/bin/kill.sh b/nebulous/ems-core/baguette-client/bin/kill.sh similarity index 100% rename from ems-core/baguette-client/bin/kill.sh rename to nebulous/ems-core/baguette-client/bin/kill.sh diff --git a/ems-core/baguette-client/bin/run.bat b/nebulous/ems-core/baguette-client/bin/run.bat similarity index 100% rename from ems-core/baguette-client/bin/run.bat rename to nebulous/ems-core/baguette-client/bin/run.bat diff --git a/ems-core/baguette-client/bin/run.sh b/nebulous/ems-core/baguette-client/bin/run.sh similarity index 100% rename from ems-core/baguette-client/bin/run.sh rename to nebulous/ems-core/baguette-client/bin/run.sh diff --git a/ems-core/baguette-client/conf/baguette-client.properties.sample b/nebulous/ems-core/baguette-client/conf/baguette-client.properties.sample similarity index 100% rename from ems-core/baguette-client/conf/baguette-client.properties.sample rename to nebulous/ems-core/baguette-client/conf/baguette-client.properties.sample diff --git a/ems-core/baguette-client/conf/baguette-client.yml b/nebulous/ems-core/baguette-client/conf/baguette-client.yml similarity index 100% rename from ems-core/baguette-client/conf/baguette-client.yml rename to nebulous/ems-core/baguette-client/conf/baguette-client.yml diff --git a/ems-core/baguette-client/conf/baguette.json b/nebulous/ems-core/baguette-client/conf/baguette.json similarity index 100% rename from ems-core/baguette-client/conf/baguette.json rename to nebulous/ems-core/baguette-client/conf/baguette.json diff --git a/ems-core/baguette-client/conf/logback-spring.xml b/nebulous/ems-core/baguette-client/conf/logback-spring.xml similarity index 100% rename from ems-core/baguette-client/conf/logback-spring.xml rename to nebulous/ems-core/baguette-client/conf/logback-spring.xml diff --git a/ems-core/baguette-client/conf/netdata.json b/nebulous/ems-core/baguette-client/conf/netdata.json similarity index 100% rename from ems-core/baguette-client/conf/netdata.json rename to nebulous/ems-core/baguette-client/conf/netdata.json diff --git a/ems-core/baguette-client/logs/output.txt b/nebulous/ems-core/baguette-client/logs/output.txt similarity index 100% rename from ems-core/baguette-client/logs/output.txt rename to nebulous/ems-core/baguette-client/logs/output.txt diff --git a/ems-core/baguette-client/pom.xml b/nebulous/ems-core/baguette-client/pom.xml similarity index 100% rename from ems-core/baguette-client/pom.xml rename to nebulous/ems-core/baguette-client/pom.xml diff --git a/ems-core/baguette-client/src/main/assembly/baguette-client-installation-package.xml b/nebulous/ems-core/baguette-client/src/main/assembly/baguette-client-installation-package.xml similarity index 100% rename from ems-core/baguette-client/src/main/assembly/baguette-client-installation-package.xml rename to nebulous/ems-core/baguette-client/src/main/assembly/baguette-client-installation-package.xml diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClient.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClient.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClient.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClient.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientCLI.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientCLI.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientCLI.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientCLI.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientProperties.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientProperties.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientProperties.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/BaguetteClientProperties.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Collector.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Collector.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Collector.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Collector.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/CommandExecutor.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/CommandExecutor.java similarity index 98% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/CommandExecutor.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/CommandExecutor.java index e52e236..3f64ed3 100644 --- a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/CommandExecutor.java +++ b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/CommandExecutor.java @@ -654,6 +654,8 @@ public class CommandExecutor { log.info("Cluster: configuration:\n{}", clusterManagerProperties); } else if ("GET-STATS".equals(cmd)) { getStatistics(args[1]); + } else if ("COLLECT-STATS".equals(cmd)) { + collectStatistics(); } else if ("SEND-STATS".equals(cmd)) { if (args.length < 2) { log.warn("Too few arguments"); @@ -1260,6 +1262,29 @@ public class CommandExecutor { if (out!=null) out.println("-INPUT:"+inputUuid+":"+SerializationUtil.serializeToString(statsMap)); } + private void collectStatistics() { + try { + // Run system metrics collection script + log.debug("Running system metrics collection..."); + boolean result = systemResourceMonitor.runImmediatelyBlocking(-1); // >=0: timeout in millis; <0: wait forever + log.debug("Running system metrics collection... {}", result ? "done" : "cancel/timeout"); + + // Collect metrics + Map statsMap = brokerCepService.getBrokerCepStatistics(); + log.debug("BCEP Statistics: {}", statsMap); + Map sysMap = systemResourceMonitor.getLatestMeasurements(); + log.debug("System Statistics: {}", sysMap); + + // Prepare and send response + Map clientStats = new HashMap<>(); + if (statsMap!=null) clientStats.putAll(statsMap); + if (sysMap!=null) clientStats.putAll(sysMap); + if (out!=null) out.println("-STATS:" + SerializationUtil.serializeToString(statsMap)); + } catch (Exception ex) { + log.error("Exception while getting Statistics to server: ", ex); + } + } + @SneakyThrows private void sendStatisticsStart() { statsSendTask = taskScheduler.scheduleWithFixedDelay(() -> { diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Sshc.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Sshc.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Sshc.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/Sshc.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/AbstractLogBase.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/AbstractLogBase.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/AbstractLogBase.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/AbstractLogBase.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/BrokerUtil.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/BrokerUtil.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/BrokerUtil.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/BrokerUtil.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterCLI.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterCLI.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterCLI.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterCLI.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManager.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManager.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManager.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManager.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManagerProperties.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManagerProperties.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManagerProperties.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterManagerProperties.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterTest.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterTest.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterTest.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/ClusterTest.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberScoreFunction.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberScoreFunction.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberScoreFunction.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberScoreFunction.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberWithScore.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberWithScore.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberWithScore.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/MemberWithScore.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/TestCallback.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/TestCallback.java similarity index 97% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/TestCallback.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/TestCallback.java index ad1cd83..2f43870 100644 --- a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/TestCallback.java +++ b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/cluster/TestCallback.java @@ -75,7 +75,7 @@ public class TestCallback extends AbstractLogBase implements BrokerUtil.NodeCall } public String getConfiguration(Member local) { - return String.format("ssl://%s:61617", local.address().host()); + return "ssl://%s:61617".formatted(local.address().host()); } public void setConfiguration(String newConfig) { diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/ClientCollectorContext.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/ClientCollectorContext.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/ClientCollectorContext.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/ClientCollectorContext.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/netdata/NetdataCollector.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/netdata/NetdataCollector.java similarity index 78% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/netdata/NetdataCollector.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/netdata/NetdataCollector.java index e41191a..8d3db8a 100644 --- a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/netdata/NetdataCollector.java +++ b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/netdata/NetdataCollector.java @@ -50,19 +50,8 @@ public class NetdataCollector extends gr.iccs.imu.ems.common.collector.netdata.N if (grp!=null) topics.addAll(grp.getEventTypeNames()); } - log.warn("Collectors::Netdata: activeGroupingChanged: New Allowed Topics for active grouping: {} -- {}", newGrouping, topics); - List tmpList = new ArrayList<>(topics); - Map tmpMap = null; - if (properties.getAllowedTopics()!=null) { - tmpMap = properties.getAllowedTopics().stream() - .map(s -> s.split(":", 2)) - .collect(Collectors.toMap(a -> a[0], a -> a.length>1 ? a[1]: "")); - } - log.warn("Collectors::Netdata: activeGroupingChanged: New Allowed Topics -- Topics Map: {} -- {}", tmpList, tmpMap); - synchronized (this) { - this.allowedTopics = tmpList; - this.topicMap = tmpMap; - } + log.info("Collectors::Netdata: activeGroupingChanged: New Allowed Topics for active grouping: {} -- {}", newGrouping, topics); + processAllowedTopics(topics); } } diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/prometheus/PrometheusCollector.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/prometheus/PrometheusCollector.java similarity index 78% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/prometheus/PrometheusCollector.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/prometheus/PrometheusCollector.java index d0cc573..cea61df 100644 --- a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/prometheus/PrometheusCollector.java +++ b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/collector/prometheus/PrometheusCollector.java @@ -50,19 +50,8 @@ public class PrometheusCollector extends gr.iccs.imu.ems.common.collector.promet if (grp!=null) topics.addAll(grp.getEventTypeNames()); } - log.warn("Collectors::Prometheus: activeGroupingChanged: New Allowed Topics for active grouping: {} -- {}", newGrouping, topics); - List tmpList = new ArrayList<>(topics); - Map tmpMap = null; - if (properties.getAllowedTopics()!=null) { - tmpMap = properties.getAllowedTopics().stream() - .map(s -> s.split(":", 2)) - .collect(Collectors.toMap(a -> a[0], a -> a.length>1 ? a[1]: "")); - } - log.warn("Collectors::Prometheus: activeGroupingChanged: New Allowed Topics -- Topics Map: {} -- {}", tmpList, tmpMap); - synchronized (this) { - this.allowedTopics = tmpList; - this.topicMap = tmpMap; - } + log.info("Collectors::Prometheus: activeGroupingChanged: New Allowed Topics for active grouping: {} -- {}", newGrouping, topics); + processAllowedTopics(topics); } } diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/NodeInfoHelper.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/NodeInfoHelper.java similarity index 100% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/NodeInfoHelper.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/NodeInfoHelper.java diff --git a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/SelfHealingPlugin.java b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/SelfHealingPlugin.java similarity index 98% rename from ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/SelfHealingPlugin.java rename to nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/SelfHealingPlugin.java index ed1c226..0bf9e70 100644 --- a/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/SelfHealingPlugin.java +++ b/nebulous/ems-core/baguette-client/src/main/java/gr/iccs/imu/ems/baguette/client/plugin/recovery/SelfHealingPlugin.java @@ -137,9 +137,8 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve private void processClusterNodeRemovedEvent(Object message) { log.debug("SelfHealingPlugin: processClusterNodeRemovedEvent(): BEGIN: message={}", message); - if (message instanceof ClusterMembershipEvent) { + if (message instanceof ClusterMembershipEvent event) { // Get removed node id and address - ClusterMembershipEvent event = (ClusterMembershipEvent)message; String nodeId = event.subject().id().id(); String nodeAddress = event.subject().address().host(); log.debug("SelfHealingPlugin: processClusterNodeRemovedEvent(): node-id={}, node-address={}", nodeId, nodeAddress); @@ -156,9 +155,8 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve private void processClusterNodeAddedEvent(Object message) { log.debug("SelfHealingPlugin: processClusterNodeAddedEvent(): BEGIN: message={}", message); - if (message instanceof ClusterMembershipEvent) { + if (message instanceof ClusterMembershipEvent event) { // Get added node id and address - ClusterMembershipEvent event = (ClusterMembershipEvent)message; String nodeId = event.subject().id().id(); String nodeAddress = event.subject().address().host(); log.debug("SelfHealingPlugin: processClusterNodeAddedEvent(): node-id={}, node-address={}", nodeId, nodeAddress); diff --git a/ems-core/baguette-client/src/main/resources/META-INF/spring.factories b/nebulous/ems-core/baguette-client/src/main/resources/META-INF/spring.factories similarity index 100% rename from ems-core/baguette-client/src/main/resources/META-INF/spring.factories rename to nebulous/ems-core/baguette-client/src/main/resources/META-INF/spring.factories diff --git a/ems-core/baguette-client/src/main/resources/banner-1.txt b/nebulous/ems-core/baguette-client/src/main/resources/banner-1.txt similarity index 100% rename from ems-core/baguette-client/src/main/resources/banner-1.txt rename to nebulous/ems-core/baguette-client/src/main/resources/banner-1.txt diff --git a/ems-core/baguette-client/src/main/resources/banner.txt b/nebulous/ems-core/baguette-client/src/main/resources/banner.txt similarity index 100% rename from ems-core/baguette-client/src/main/resources/banner.txt rename to nebulous/ems-core/baguette-client/src/main/resources/banner.txt diff --git a/ems-core/baguette-server/pom.xml b/nebulous/ems-core/baguette-server/pom.xml similarity index 93% rename from ems-core/baguette-server/pom.xml rename to nebulous/ems-core/baguette-server/pom.xml index bd67ebb..12a70aa 100644 --- a/ems-core/baguette-server/pom.xml +++ b/nebulous/ems-core/baguette-server/pom.xml @@ -77,15 +77,14 @@ lombok provided + org.springframework.boot spring-boot-starter - - javax.validation - validation-api - 2.0.1.Final + org.springframework.boot + spring-boot-starter-validation @@ -98,7 +97,7 @@ org.glassfish.jersey.core jersey-common - 3.1.3 + 3.1.4 diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/BaguetteServer.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/BaguetteServer.java similarity index 99% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/BaguetteServer.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/BaguetteServer.java index 9b39da6..510d636 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/BaguetteServer.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/BaguetteServer.java @@ -376,7 +376,7 @@ public class BaguetteServer implements InitializingBean, EventBus.EventConsumer< }) .sorted(Comparator.comparing(m -> m.get("id"))) .collect(Collectors.toMap(m -> m.get("id"), m -> m, - (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }, + (u,v) -> { throw new IllegalStateException("Duplicate key %s".formatted(u)); }, LinkedHashMap::new)); } diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ClientShellCommand.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ClientShellCommand.java similarity index 98% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ClientShellCommand.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ClientShellCommand.java index e36664b..7a9de39 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ClientShellCommand.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ClientShellCommand.java @@ -30,7 +30,7 @@ import org.apache.sshd.server.session.ServerSessionAware; import org.cryptacular.util.CertUtil; import org.slf4j.event.Level; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; import java.io.*; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; @@ -115,7 +115,7 @@ public class ClientShellCommand implements Command, Runnable, ServerSessionAware public ClientShellCommand(ServerCoordinator coordinator, boolean allowClientOverrideItsAddress, EventBus eventBus, NodeRegistry registry) { synchronized (LOCK) { - id = String.format("#%05d", counter.getAndIncrement()); + id = "#%05d".formatted(counter.getAndIncrement()); } this.coordinator = coordinator; this.clientAddressOverrideAllowed = allowClientOverrideItsAddress; @@ -688,8 +688,9 @@ public class ClientShellCommand implements Command, Runnable, ServerSessionAware log.debug("sendGroupingConfiguration: id={}, grouping={}, grouping-config={}", id, grouping, gc); try { String allStr = serializeToString(gc); - log.info("sendGroupingConfiguration: Serialization of Grouping configuration for {}: {}", grouping, allStr); - sendToClient("SET-GROUPING-CONFIG " + allStr); + log.debug("sendGroupingConfiguration: Serialization of Grouping configuration for {}: {}", grouping, allStr); + sendToClient("SET-GROUPING-CONFIG " + allStr, Level.DEBUG); + log.info("sendGroupingConfiguration: Sent grouping configuration for {}", grouping); } catch (IOException ex) { log.error("sendGroupingConfiguration: Exception while serializing Grouping configuration: ", ex); log.error("sendGroupingConfiguration: SET-GROUPING-CONFIG command *NOT* sent to client"); diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/GroupingConfigurationHelper.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/GroupingConfigurationHelper.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/GroupingConfigurationHelper.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/GroupingConfigurationHelper.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistry.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistry.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistry.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistry.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistryEntry.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistryEntry.java similarity index 96% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistryEntry.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistryEntry.java index 6b42b90..2032e63 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistryEntry.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistryEntry.java @@ -95,8 +95,8 @@ public class NodeRegistryEntry { private void _canUpdateEntry(@NonNull STATE newState) { if (! canChangeStateTo(newState)) { - throw new IllegalStateException(String.format("Cannot change NodeRegistryEntry state from %s to %s: client-id=%s, client-address=%s", - state, newState, clientId, ipAddress)); + throw new IllegalStateException("Cannot change NodeRegistryEntry state from %s to %s: client-id=%s, client-address=%s" + .formatted(state, newState, clientId, ipAddress)); } } @@ -112,7 +112,7 @@ public class NodeRegistryEntry { _canUpdateEntry(newState); if (clear) map.clear(); map.put(key, val!=null ? val.toString() : defVal); - setState(STATE.IGNORE_NODE); + setState(newState); return this; } diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ServerCoordinator.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ServerCoordinator.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ServerCoordinator.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/ServerCoordinator.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/Sshd.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/Sshd.java similarity index 99% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/Sshd.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/Sshd.java index 29e9a6c..5c5da67 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/Sshd.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/Sshd.java @@ -155,7 +155,7 @@ public class Sshd { Thread.sleep(period); } catch (InterruptedException ex) { } - String msg = String.format("Heartbeat %d", System.currentTimeMillis()); + String msg = "Heartbeat %d".formatted(System.currentTimeMillis()); log.debug("--> Heartbeat: {}", msg); for (ClientShellCommand csc : ClientShellCommand.getActive()) { csc.sendToClient(msg, Level.DEBUG); diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/NoopCoordinator.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/NoopCoordinator.java similarity index 92% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/NoopCoordinator.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/NoopCoordinator.java index cc26d39..4f78422 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/NoopCoordinator.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/NoopCoordinator.java @@ -86,11 +86,11 @@ public class NoopCoordinator implements ServerCoordinator { protected boolean _logInvocation(String methodName, Object o, boolean checkStarted) { String className = getClass().getSimpleName(); String str = (o==null) ? "" : ( - o instanceof ClientShellCommand ? String.format(". CSC: %s", o) : ( - o instanceof NodeRegistryEntry ? String.format(". NRE: %s", o) : - String.format(". Object: %s", o) - ) - ); + o instanceof ClientShellCommand + ? ". CSC: %s".formatted(o) + : (o instanceof NodeRegistryEntry + ? ". NRE: %s".formatted(o) + : ". Object: %s".formatted(o)) ); if (checkStarted && !started) { log.warn("{}: {}(): Coordinator has not been started{}", className, methodName, str); } else diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorTimeWin.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorTimeWin.java similarity index 96% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorTimeWin.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorTimeWin.java index e1199a1..965cd57 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorTimeWin.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorTimeWin.java @@ -144,8 +144,8 @@ public class ServerCoordinatorTimeWin implements ServerCoordinator { int brokerPort = broker.getClientPort(); if (brokerIpAddress == null || brokerIpAddress.trim().isEmpty() || brokerPort <= 0) throw new Exception("ServerCoordinatorTimeWin: startPhase1(): Unable to get broker IP address or Port: " + broker); - this.brokerCfgIpAddressCmd = String.format("SET-PARAM bin/broker.cfg-template BROKER_IP_ADDR %s bin/broker.cfg", brokerIpAddress); - this.brokerCfgPortCmd = String.format("SET-PARAM bin/broker.cfg-template BROKER_PORT %d bin/broker.cfg", brokerPort); + this.brokerCfgIpAddressCmd = "SET-PARAM bin/broker.cfg-template BROKER_IP_ADDR %s bin/broker.cfg".formatted(brokerIpAddress); + this.brokerCfgPortCmd = "SET-PARAM bin/broker.cfg-template BROKER_PORT %d bin/broker.cfg".formatted(brokerPort); } catch (Exception ex) { this.brokerCfgIpAddressCmd = null; this.brokerCfgPortCmd = null; diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorWaitAll.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorWaitAll.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorWaitAll.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/ServerCoordinatorWaitAll.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TestCoordinator.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TestCoordinator.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TestCoordinator.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TestCoordinator.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TwoLevelCoordinator.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TwoLevelCoordinator.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TwoLevelCoordinator.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/TwoLevelCoordinator.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/AtLeastTwoZoneManagementStrategy.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/AtLeastTwoZoneManagementStrategy.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/AtLeastTwoZoneManagementStrategy.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/AtLeastTwoZoneManagementStrategy.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterSelfHealing.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterSelfHealing.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterSelfHealing.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterSelfHealing.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZone.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZone.java similarity index 99% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZone.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZone.java index 5d9cdc9..f99ce64 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZone.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZone.java @@ -20,7 +20,7 @@ import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.operator.OperatorCreationException; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; import java.io.File; import java.io.IOException; import java.security.KeyStoreException; diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZoneDetector.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZoneDetector.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZoneDetector.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusterZoneDetector.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusteringCoordinator.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusteringCoordinator.java similarity index 99% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusteringCoordinator.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusteringCoordinator.java index 0081575..7490e4b 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusteringCoordinator.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/ClusteringCoordinator.java @@ -22,6 +22,7 @@ import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringSubstitutor; +import org.slf4j.event.Level; import java.util.*; import java.util.stream.Collectors; @@ -383,9 +384,10 @@ public class ClusteringCoordinator extends NoopCoordinator { // ------------------------------------------------------------------------ void sendClusterKey(ClientShellCommand csc, IClusterZone zoneInfo) { - csc.sendCommand(String.format("CLUSTER-KEY %s %s %s %s", + csc.sendCommand("CLUSTER-KEY %s %s %s %s".formatted( zoneInfo.getClusterKeystoreFile().getName(), zoneInfo.getClusterKeystoreType(), - zoneInfo.getClusterKeystorePassword(), zoneInfo.getClusterKeystoreBase64())); + zoneInfo.getClusterKeystorePassword(), zoneInfo.getClusterKeystoreBase64()), Level.DEBUG); + log.info("sendClusterKey: Sent cluster key to node {}", csc.getClientIpAddress()); } void sendCommandToZone(String command, List zoneNodes) { diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/DefaultZoneManagementStrategy.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/DefaultZoneManagementStrategy.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/DefaultZoneManagementStrategy.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/DefaultZoneManagementStrategy.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZone.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZone.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZone.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZone.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZoneDetector.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZoneDetector.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZoneDetector.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IClusterZoneDetector.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IZoneManagementStrategy.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IZoneManagementStrategy.java similarity index 100% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IZoneManagementStrategy.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/coordinator/cluster/IZoneManagementStrategy.java diff --git a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/properties/BaguetteServerProperties.java b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/properties/BaguetteServerProperties.java similarity index 97% rename from ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/properties/BaguetteServerProperties.java rename to nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/properties/BaguetteServerProperties.java index 831bd37..d8dd180 100644 --- a/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/properties/BaguetteServerProperties.java +++ b/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/properties/BaguetteServerProperties.java @@ -19,8 +19,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/ems-core/bin/client.sh b/nebulous/ems-core/bin/client.sh similarity index 100% rename from ems-core/bin/client.sh rename to nebulous/ems-core/bin/client.sh diff --git a/ems-core/bin/cp2cdo.bat b/nebulous/ems-core/bin/cp2cdo.bat similarity index 100% rename from ems-core/bin/cp2cdo.bat rename to nebulous/ems-core/bin/cp2cdo.bat diff --git a/ems-core/bin/cp2cdo.sh b/nebulous/ems-core/bin/cp2cdo.sh similarity index 100% rename from ems-core/bin/cp2cdo.sh rename to nebulous/ems-core/bin/cp2cdo.sh diff --git a/ems-core/bin/detect.sh b/nebulous/ems-core/bin/detect.sh similarity index 100% rename from ems-core/bin/detect.sh rename to nebulous/ems-core/bin/detect.sh diff --git a/ems-core/bin/initialize-MELODIC-keystores.sh b/nebulous/ems-core/bin/initialize-MELODIC-keystores.sh similarity index 100% rename from ems-core/bin/initialize-MELODIC-keystores.sh rename to nebulous/ems-core/bin/initialize-MELODIC-keystores.sh diff --git a/ems-core/bin/initialize-keystores.bat b/nebulous/ems-core/bin/initialize-keystores.bat similarity index 100% rename from ems-core/bin/initialize-keystores.bat rename to nebulous/ems-core/bin/initialize-keystores.bat diff --git a/ems-core/bin/initialize-keystores.sh b/nebulous/ems-core/bin/initialize-keystores.sh similarity index 100% rename from ems-core/bin/initialize-keystores.sh rename to nebulous/ems-core/bin/initialize-keystores.sh diff --git a/ems-core/bin/jwtutil.bat b/nebulous/ems-core/bin/jwtutil.bat similarity index 94% rename from ems-core/bin/jwtutil.bat rename to nebulous/ems-core/bin/jwtutil.bat index 75e3dab..71771d5 100644 --- a/ems-core/bin/jwtutil.bat +++ b/nebulous/ems-core/bin/jwtutil.bat @@ -25,7 +25,7 @@ if "%JASYPT_PASSWORD%"=="" ( set /p JASYPT_PASSWORD="Configuration Password: " ) -java -Djasypt.encryptor.password=%JASYPT_PASSWORD% -cp %JARS_DIR%\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR "-Dspring.config.location=%EMS_CONFIG_LOCATION%" org.springframework.boot.loader.PropertiesLauncher %* +java -Djasypt.encryptor.password=%JASYPT_PASSWORD% -cp %JARS_DIR%\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR "-Dspring.config.location=%EMS_CONFIG_LOCATION%" org.springframework.boot.loader.launch.PropertiesLauncher %* set exitcode=%ERRORLEVEL% cd %PWD% diff --git a/ems-core/bin/jwtutil.sh b/nebulous/ems-core/bin/jwtutil.sh similarity index 95% rename from ems-core/bin/jwtutil.sh rename to nebulous/ems-core/bin/jwtutil.sh index 26df3f0..53e558e 100644 --- a/ems-core/bin/jwtutil.sh +++ b/nebulous/ems-core/bin/jwtutil.sh @@ -26,7 +26,7 @@ if [[ -z "$JASYPT_PASSWORD" ]]; then read -s JASYPT_PASSWORD fi -java -Djasypt.encryptor.password=$JASYPT_PASSWORD -cp ${JARS_DIR}/control-service.jar -Dloader.main=gr.iccs.imu.ems.control.util.jwt.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR "-Dspring.config.location=$EMS_CONFIG_LOCATION" org.springframework.boot.loader.PropertiesLauncher $* +java -Djasypt.encryptor.password=$JASYPT_PASSWORD -cp ${JARS_DIR}/control-service.jar -Dloader.main=gr.iccs.imu.ems.control.util.jwt.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR "-Dspring.config.location=$EMS_CONFIG_LOCATION" org.springframework.boot.loader.launch.PropertiesLauncher $* exitcode=$? cd $PREVWORKDIR diff --git a/ems-core/bin/run.bat b/nebulous/ems-core/bin/run.bat similarity index 98% rename from ems-core/bin/run.bat rename to nebulous/ems-core/bin/run.bat index fa74e74..a65bb98 100644 --- a/ems-core/bin/run.bat +++ b/nebulous/ems-core/bin/run.bat @@ -78,7 +78,7 @@ java %EMS_DEBUG_OPTS% %JAVA_OPTS% %JAVA_ADD_OPENS% ^ -Dscan.packages=%SCAN_PACKAGES% ^ %CP% ^ "-Dloader.path=%ESPER_PATH%%EXTRA_LOADER_PATHS%" ^ - org.springframework.boot.loader.PropertiesLauncher ^ + org.springframework.boot.loader.launch.PropertiesLauncher ^ -nolog ^ "--spring.config.location=%EMS_CONFIG_LOCATION%" ^ "--logging.config=file:%LOG_CONFIG_FILE%" ^ diff --git a/ems-core/bin/run.sh b/nebulous/ems-core/bin/run.sh similarity index 98% rename from ems-core/bin/run.sh rename to nebulous/ems-core/bin/run.sh index ef22880..9ded56e 100644 --- a/ems-core/bin/run.sh +++ b/nebulous/ems-core/bin/run.sh @@ -87,7 +87,7 @@ while :; do -Dscan.packages=${SCAN_PACKAGES} \ ${CP} \ -Dloader.path=${ESPER_PATH}${EXTRA_LOADER_PATHS} \ - org.springframework.boot.loader.PropertiesLauncher \ + org.springframework.boot.loader.launch.PropertiesLauncher \ "--spring.config.location=${EMS_CONFIG_LOCATION}" \ "--logging.config=file:$LOG_CONFIG_FILE" \ $* & diff --git a/ems-core/bin/sysmon.sh b/nebulous/ems-core/bin/sysmon.sh similarity index 100% rename from ems-core/bin/sysmon.sh rename to nebulous/ems-core/bin/sysmon.sh diff --git a/ems-core/bin/update-credentials.sh b/nebulous/ems-core/bin/update-credentials.sh similarity index 100% rename from ems-core/bin/update-credentials.sh rename to nebulous/ems-core/bin/update-credentials.sh diff --git a/ems-core/broker-cep/client.bat b/nebulous/ems-core/broker-cep/client.bat similarity index 100% rename from ems-core/broker-cep/client.bat rename to nebulous/ems-core/broker-cep/client.bat diff --git a/ems-core/broker-cep/pom.xml b/nebulous/ems-core/broker-cep/pom.xml similarity index 97% rename from ems-core/broker-cep/pom.xml rename to nebulous/ems-core/broker-cep/pom.xml index 294b2c1..e192702 100644 --- a/ems-core/broker-cep/pom.xml +++ b/nebulous/ems-core/broker-cep/pom.xml @@ -27,7 +27,7 @@ ${project.version} - + + + + org.springframework.boot + spring-boot-starter-validation + org.springframework.boot @@ -157,13 +162,6 @@ provided - - - org.hibernate.validator - hibernate-validator - ${hibernate-validator.version} - - org.apache.commons commons-lang3 @@ -244,7 +242,7 @@ commons-io commons-io - 2.13.0 + 2.15.1 @@ -308,6 +306,9 @@ ${project.build.outputDirectory}/git.properties full --> + + false + org.apache.maven.plugins @@ -603,6 +604,7 @@ 1.2.0 + read-docker-image-properties validate read-project-properties @@ -685,12 +687,12 @@ - + + <!–https://localhost:2376–> true true @@ -711,6 +713,36 @@ + --> + + + + com.internetitem + write-properties-file-maven-plugin + 1.0.1 + + + write-docker-image-properties-file + install + + write-properties-file + + + docker-image.properties + ${project.build.directory}/ + + + docker.image.name + ${docker.image.name} + + + docker.image.tag + ${docker.image.tag} + + + + + diff --git a/ems-core/control-service/src/main/docker/Dockerfile b/nebulous/ems-core/control-service/src/main/docker/Dockerfile similarity index 62% rename from ems-core/control-service/src/main/docker/Dockerfile rename to nebulous/ems-core/control-service/src/main/docker/Dockerfile index d75c94b..ab1e615 100644 --- a/ems-core/control-service/src/main/docker/Dockerfile +++ b/nebulous/ems-core/control-service/src/main/docker/Dockerfile @@ -7,18 +7,20 @@ # https://www.mozilla.org/en-US/MPL/2.0/ # -ARG BUILDER_IMAGE=eclipse-temurin:17.0.8_7-jre -ARG RUN_IMAGE=eclipse-temurin:17.0.8_7-jre +ARG BUILDER_IMAGE=eclipse-temurin +ARG BUILDER_IMAGE_TAG=21.0.1_12-jre +ARG RUN_IMAGE=eclipse-temurin +ARG RUN_IMAGE_TAG=21.0.1_12-jre # ----------------- Builder image ----------------- -FROM $BUILDER_IMAGE as ems-server-builder +FROM $BUILDER_IMAGE:$BUILDER_IMAGE_TAG as ems-server-builder #FROM vegardit/graalvm-maven:latest-java17 WORKDIR /app COPY jars/control-service.jar . RUN java -Djarmode=layertools -jar control-service.jar extract # ----------------- Run image ----------------- -FROM $RUN_IMAGE +FROM $RUN_IMAGE:$RUN_IMAGE_TAG # Setup environment ENV BASEDIR /opt/ems-server @@ -31,18 +33,18 @@ ENV LOGS_DIR ${BASEDIR}/logs ENV PUBLIC_DIR ${BASEDIR}/public_resources # Install required and optional packages -RUN apt-get update && apt-get install -y \ - dumb-init \ - netcat \ - vim \ - iputils-ping \ - && rm -rf /var/lib/apt/lists/* +RUN wget --progress=dot:giga -O /usr/local/bin/dumb-init \ + https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 && \ + chmod +x /usr/local/bin/dumb-init +#RUN apt-get update \ +# && apt-get install -y netcat vim iputils-ping \ +# && rm -rf /var/lib/apt/lists/* # Add an EMS user ARG EMS_USER=emsuser -RUN mkdir ${EMS_HOME} ; \ - addgroup ${EMS_USER} ; \ - adduser --home ${EMS_HOME} --no-create-home --ingroup ${EMS_USER} --disabled-password ${EMS_USER} ; \ +RUN mkdir ${EMS_HOME} && \ + addgroup ${EMS_USER} && \ + adduser --home ${EMS_HOME} --no-create-home --ingroup ${EMS_USER} --disabled-password ${EMS_USER} && \ chown ${EMS_USER}:${EMS_USER} ${EMS_HOME} USER ${EMS_USER} @@ -50,17 +52,17 @@ WORKDIR ${BASEDIR} # Download a JRE suitable for running EMS clients, and # offer it for download -ENV JRE_LINUX_PACKAGE zulu17.44.15-ca-jre17.0.8-linux_x64.tar.gz -RUN mkdir -p ${PUBLIC_DIR}/resources -RUN curl https://cdn.azul.com/zulu/bin/${JRE_LINUX_PACKAGE} --output ${PUBLIC_DIR}/resources/${JRE_LINUX_PACKAGE} +ENV JRE_LINUX_PACKAGE zulu21.30.15-ca-jre21.0.1-linux_x64.tar.gz +RUN mkdir -p ${PUBLIC_DIR}/resources && \ + wget --progress=dot:giga -O ${PUBLIC_DIR}/resources/${JRE_LINUX_PACKAGE} https://cdn.azul.com/zulu/bin/${JRE_LINUX_PACKAGE} # Copy resource files to image -ADD --chown=${EMS_USER}:${EMS_USER} bin ${BIN_DIR} -ADD --chown=${EMS_USER}:${EMS_USER} config ${CONFIG_DIR} -ADD --chown=${EMS_USER}:${EMS_USER} public_resources ${PUBLIC_DIR} +COPY --chown=${EMS_USER}:${EMS_USER} bin ${BIN_DIR} +COPY --chown=${EMS_USER}:${EMS_USER} config ${CONFIG_DIR} +COPY --chown=${EMS_USER}:${EMS_USER} public_resources ${PUBLIC_DIR} -RUN mkdir ${LOGS_DIR} -RUN chmod +rx ${BIN_DIR}/*.sh +RUN mkdir ${LOGS_DIR} && \ + chmod +rx ${BIN_DIR}/*.sh # Copy files from builder container COPY --chown=${EMS_USER}:${EMS_USER} --from=ems-server-builder /app/dependencies ${BASEDIR} diff --git a/ems-core/control-service/src/main/docker/Dockerfile-alpine b/nebulous/ems-core/control-service/src/main/docker/Dockerfile-alpine similarity index 76% rename from ems-core/control-service/src/main/docker/Dockerfile-alpine rename to nebulous/ems-core/control-service/src/main/docker/Dockerfile-alpine index 56c62e9..82c244d 100644 --- a/ems-core/control-service/src/main/docker/Dockerfile-alpine +++ b/nebulous/ems-core/control-service/src/main/docker/Dockerfile-alpine @@ -7,8 +7,8 @@ # https://www.mozilla.org/en-US/MPL/2.0/ # -ARG BUILDER_IMAGE=eclipse-temurin:17.0.8_7-jre-alpine -ARG RUN_IMAGE=eclipse-temurin:17.0.8_7-jre-alpine +ARG BUILDER_IMAGE=eclipse-temurin:21.0.1_12-jre-alpine +ARG RUN_IMAGE=eclipse-temurin:21.0.1_12-jre-alpine # ----------------- Builder image ----------------- FROM $BUILDER_IMAGE as ems-server-builder @@ -31,17 +31,17 @@ ENV LOGS_DIR ${BASEDIR}/logs ENV PUBLIC_DIR ${BASEDIR}/public_resources # Install required and optional packages -RUN apk update && apk add \ - dumb-init curl bash \ - netcat-openbsd \ - vim \ - iputils-ping +RUN apk update && \ + apk add curl bash netcat-openbsd vim iputils-ping +RUN wget -O /usr/local/bin/dumb-init \ + https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 && \ + chmod +x /usr/local/bin/dumb-init # Add an EMS user ARG EMS_USER=emsuser -RUN mkdir ${EMS_HOME} ; \ - addgroup ${EMS_USER} ; \ - adduser --home ${EMS_HOME} --no-create-home --ingroup ${EMS_USER} --disabled-password ${EMS_USER} ; \ +RUN mkdir ${EMS_HOME} && \ + addgroup ${EMS_USER} && \ + adduser --home ${EMS_HOME} --no-create-home --ingroup ${EMS_USER} --disabled-password ${EMS_USER} && \ chown ${EMS_USER}:${EMS_USER} ${EMS_HOME} USER ${EMS_USER} @@ -49,9 +49,9 @@ WORKDIR ${BASEDIR} # Download a JRE suitable for running EMS clients, and # offer it for download -ENV JRE_LINUX_PACKAGE zulu17.44.15-ca-jre17.0.8-linux_x64.tar.gz -RUN mkdir -p ${PUBLIC_DIR}/resources -RUN curl https://cdn.azul.com/zulu/bin/${JRE_LINUX_PACKAGE} --output ${PUBLIC_DIR}/resources/${JRE_LINUX_PACKAGE} +ENV JRE_LINUX_PACKAGE zulu21.30.15-ca-jre21.0.1-linux_x64.tar.gz +RUN mkdir -p ${PUBLIC_DIR}/resources && \ + curl https://cdn.azul.com/zulu/bin/${JRE_LINUX_PACKAGE} --output ${PUBLIC_DIR}/resources/${JRE_LINUX_PACKAGE} # Copy resource files to image ADD --chown=${EMS_USER}:${EMS_USER} bin ${BIN_DIR} diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ApplicationContext.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ApplicationContext.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ApplicationContext.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ApplicationContext.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ControlServiceApplication.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ControlServiceApplication.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ControlServiceApplication.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/ControlServiceApplication.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/Collector.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/Collector.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/Collector.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/Collector.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/ServerCollectorContext.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/ServerCollectorContext.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/ServerCollectorContext.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/ServerCollectorContext.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/netdata/ServerNetdataCollector.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/netdata/ServerNetdataCollector.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/netdata/ServerNetdataCollector.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/collector/netdata/ServerNetdataCollector.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/BrokerCepController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/BrokerCepController.java similarity index 84% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/BrokerCepController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/BrokerCepController.java index ae7e075..92282ba 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/BrokerCepController.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/BrokerCepController.java @@ -12,15 +12,13 @@ package gr.iccs.imu.ems.control.controller; import gr.iccs.imu.ems.brokercep.EventCache; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Collection; import java.util.List; -import static org.springframework.web.bind.annotation.RequestMethod.GET; - @Slf4j @RestController @RequiredArgsConstructor @@ -28,7 +26,7 @@ public class BrokerCepController { private final EventCache eventCache; - @RequestMapping(value = { "/brokercep/last-events/{howmany}", "/brokercep/last-events" }, method=GET) + @GetMapping({ "/brokercep/last-events/{howmany}", "/brokercep/last-events" }) public Collection getLastEvents(@PathVariable(required = false) Integer howmany) { log.info("BrokerCepController.getLastEvents(): howmany={}", howmany); diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceController.java similarity index 76% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceController.java index 8023a7d..8050753 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceController.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceController.java @@ -10,6 +10,7 @@ package gr.iccs.imu.ems.control.controller; import com.google.gson.reflect.TypeToken; +import gr.iccs.imu.ems.translate.TranslationContext; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,9 +29,6 @@ import java.lang.reflect.Type; import java.util.*; import java.util.stream.Collectors; -import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.POST; - @Slf4j @RestController @RequiredArgsConstructor @@ -47,8 +45,7 @@ public class ControlServiceController { // Application Model methods // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = { "/appModel", "/appModelJson" }, method = POST, - consumes = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(value = { "/appModel", "/appModelJson" }, consumes = MediaType.APPLICATION_JSON_VALUE) public String newAppModel(@RequestBody String requestStr, @RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) { @@ -58,9 +55,13 @@ public class ControlServiceController { // Use Gson to get model id's from request body (in JSON format) com.google.gson.JsonObject jObj = new com.google.gson.Gson().fromJson(requestStr, com.google.gson.JsonObject.class); String appModelId = Optional.ofNullable(jObj.get("app-model-id")).map(je -> stripQuotes(je.toString())).orElse(null); - String cpModelId = Optional.ofNullable(jObj.get("cp-model-id")).map(je -> stripQuotes(je.toString())).orElse(null); - log.info("ControlServiceController.newAppModel(): App model id from request: {}", appModelId); - log.info("ControlServiceController.newAppModel(): CP model id from request: {}", cpModelId); + if (StringUtils.isBlank(appModelId)) + appModelId = Optional.ofNullable(jObj.get("applicationId")).map(je -> stripQuotes(je.toString())).orElse(null); + String appExecModelId = Optional.ofNullable(jObj.get("app-exec-model-id")).map(je -> stripQuotes(je.toString())).orElse(null); + if (StringUtils.isBlank(appExecModelId)) + appExecModelId = Optional.ofNullable(jObj.get("cp-model-id")).map(je -> stripQuotes(je.toString())).orElse(null); + log.info("ControlServiceController.newAppModel(): App model id from request: {}", appModelId); + log.info("ControlServiceController.newAppModel(): Exec model id from request: {}", appExecModelId); // Check parameters if (StringUtils.isBlank(appModelId)) { @@ -69,7 +70,7 @@ public class ControlServiceController { } // Start translation and component reconfiguration in a worker thread - coordinator.processAppModel(appModelId, cpModelId, ControlServiceRequestInfo.create(null, null, jwtToken)); + coordinator.processAppModel(appModelId, appExecModelId, ControlServiceRequestInfo.create(null, null, jwtToken)); log.debug("ControlServiceController.newAppModel(): Model translation dispatched to a worker thread"); return "OK"; @@ -77,8 +78,7 @@ public class ControlServiceController { // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = {"/appExecModel", "/appExecModelJson"}, method = POST, - consumes = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(value = {"/appExecModel", "/appExecModelJson"}, consumes = MediaType.APPLICATION_JSON_VALUE) public String newAppExecModel(@RequestBody String requestStr, @RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) { @@ -96,15 +96,14 @@ public class ControlServiceController { throw new RestControllerException(400, "Request does not contain an App execution model id"); } - // Start CP model processing in a worker thread - coordinator.processCpModel(appExecModelId, ControlServiceRequestInfo.create(null, null, jwtToken)); + // Start App Exec model processing in a worker thread + coordinator.processAppExecModel(appExecModelId, ControlServiceRequestInfo.create(null, null, jwtToken)); log.debug("ControlServiceController.newAppExecModel(): App Execution Model processing dispatched to a worker thread"); return "OK"; } - @RequestMapping(value = "/cpConstants", method = POST, - consumes = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(value = {"/cpConstants", "/appConstants"}, consumes = MediaType.APPLICATION_JSON_VALUE) public String setConstants(@RequestBody String requestStr, @RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) { @@ -116,7 +115,7 @@ public class ControlServiceController { Map constants = new com.google.gson.Gson().fromJson(requestStr, type); log.info("ControlServiceController.setConstants(): Constants from request: {}", constants); - // Start CP model processing in a worker thread + // Start App Exec model processing in a worker thread coordinator.setConstants(constants, ControlServiceRequestInfo.create(null, null, jwtToken)); log.debug("ControlServiceController.setConstants(): Constants set"); @@ -142,7 +141,7 @@ public class ControlServiceController { // Translator results methods // --------------------------------------------------------------------------------------------------- - @RequestMapping(value = "/translator/currentAppModel", method = {GET,POST}) + @GetMapping(value = "/translator/currentAppModel") public String getCurrentAppModel(@RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) { log.debug("ControlServiceController.getCurrentAppModel(): Received request"); @@ -154,16 +153,28 @@ public class ControlServiceController { return currentAppModelId; } - @RequestMapping(value = "/translator/currentCpModel", method = {GET,POST}) - public String getCurrentCpModel(@RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) + @GetMapping(value = "/translator/currentAppExecModel") + public String getCurrentAppExecModel(@RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) { - log.debug("ControlServiceController.getCurrentCpModel(): Received request"); - log.trace("ControlServiceController.getCurrentCpModel(): JWT token: {}", jwtToken); + log.debug("ControlServiceController.getCurrentAppExecModel(): Received request"); + log.trace("ControlServiceController.getCurrentAppExecModel(): JWT token: {}", jwtToken); - String currentCpModelId = coordinator.getCurrentCpModelId(); - log.info("ControlServiceController.getCurrentCpModel(): Current CP model: {}", currentCpModelId); + String currentAppExecModelId = coordinator.getCurrentAppExecModelId(); + log.info("ControlServiceController.getCurrentAppExecModel(): Current App Exec model: {}", currentAppExecModelId); - return currentCpModelId; + return currentAppExecModelId; + } + + @GetMapping(value = "/translator/currentTranslationContext", produces = MediaType.APPLICATION_JSON_VALUE) + public TranslationContext getCurrentTranslationContext(@RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) + { + log.debug("ControlServiceController.getCurrentTranslationContext(): Received request"); + log.trace("ControlServiceController.getCurrentTranslationContext(): JWT token: {}", jwtToken); + + TranslationContext _TC = coordinator.getTranslationContextOfAppModel(coordinator.getCurrentAppModelId()); + log.info("ControlServiceController.getCurrentAppExecModel(): Current TC model: {}", _TC.getModelName()); + + return _TC; } // --------------------------------------------------------------------------------------------------- diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceCoordinator.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceCoordinator.java similarity index 92% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceCoordinator.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceCoordinator.java index ed3e726..2d40f4b 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceCoordinator.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceCoordinator.java @@ -90,7 +90,7 @@ public class ControlServiceCoordinator implements InitializingBean { private final Map appModelToTcCache = new HashMap<>(); @Getter private String currentAppModelId; - @Getter private String currentCpModelId; + @Getter private String currentAppExecModelId; private TranslationContext currentTC; private ServerNetdataCollector netdataCollector; @@ -158,12 +158,12 @@ public class ControlServiceCoordinator implements InitializingBean { // ------------------------------------------------------------------------------------------------------------ - public String getAppModelPath() { + public String getAppModelId() { return currentAppModelId; } - public String getCpModelPath() { - return currentCpModelId; + public String getAppExecModelId() { + return currentAppExecModelId; } public TranslationContext getTranslationContextOfAppModel(String appModelId) { @@ -194,12 +194,12 @@ public class ControlServiceCoordinator implements InitializingBean { @Async public void preloadModels() { String preloadAppModel = properties.getPreload().getAppModel(); - String preloadCpModel = properties.getPreload().getCpModel(); + String preloadAppExecModel = properties.getPreload().getCpModel(); if (StringUtils.isNotBlank(preloadAppModel)) { log.info("==================================================================================================="); - log.info("ControlServiceCoordinator.preloadModels(): Preloading models: app-model={}, cp-model={}", - preloadAppModel, preloadCpModel); - processAppModel(preloadAppModel, preloadCpModel, ControlServiceRequestInfo.EMPTY); + log.info("ControlServiceCoordinator.preloadModels(): Preloading models: app-model={}, app-exec-model={}", + preloadAppModel, preloadAppExecModel); + processAppModel(preloadAppModel, preloadAppExecModel, ControlServiceRequestInfo.EMPTY); } else { log.info("ControlServiceCoordinator.preloadModels(): No model to preload"); } @@ -208,33 +208,33 @@ public class ControlServiceCoordinator implements InitializingBean { // ------------------------------------------------------------------------------------------------------------ @Async - public void processAppModel(String appModelId, String cpModelId, ControlServiceRequestInfo requestInfo) { - _lockAndProcessModel(appModelId, cpModelId, requestInfo, "processAppModel()", () -> { + public void processAppModel(String appModelId, String appExecModelId, ControlServiceRequestInfo requestInfo) { + _lockAndProcessModel(appModelId, appExecModelId, requestInfo, "processAppModel()", () -> { // Call '_processNewModels()' to do actual processing - _processAppModels(appModelId, cpModelId, requestInfo); + _processAppModels(appModelId, appExecModelId, requestInfo); this.currentAppModelId = _normalizeModelId(appModelId); - this.currentCpModelId = _normalizeModelId(cpModelId); + this.currentAppExecModelId = _normalizeModelId(appExecModelId); }); } @Async - public void processCpModel(String cpModelId, ControlServiceRequestInfo requestInfo) { - _lockAndProcessModel(null, cpModelId, requestInfo, "processCpModel()", () -> { - // Call '_processCpModel()' to do actual processing - _processCpModel(cpModelId, requestInfo); - this.currentCpModelId = _normalizeModelId(cpModelId); + public void processAppExecModel(String appExecModelId, ControlServiceRequestInfo requestInfo) { + _lockAndProcessModel(null, appExecModelId, requestInfo, "processAppExecModel()", () -> { + // Call '_processAppExecModel()' to do actual processing + _processAppExecModel(appExecModelId, requestInfo); + this.currentAppExecModelId = _normalizeModelId(appExecModelId); }); } @Async public void setConstants(@NonNull Map constants, ControlServiceRequestInfo requestInfo) { - _lockAndProcessModel(null, null, requestInfo, "processCpModel()", () -> { - // Call '_processCpModel()' to do actual processing + _lockAndProcessModel(null, null, requestInfo, "setConstants()", () -> { + // Call '_setConstants()' to do actual processing _setConstants(constants, requestInfo); }); } - protected void _lockAndProcessModel(String appModelId, String cpModelId, ControlServiceRequestInfo requestInfo, String caller, Runnable callback) { + protected void _lockAndProcessModel(String appModelId, String appExecModelId, ControlServiceRequestInfo requestInfo, String caller, Runnable callback) { // Acquire lock of this coordinator if (!inUse.compareAndSet(false, true)) { String mesg = "ControlServiceCoordinator."+caller+": ERROR: Coordinator is in use. Exits immediately"; @@ -267,8 +267,8 @@ public class ControlServiceCoordinator implements InitializingBean { // ------------------------------------------------------------------------------------------------------------ - protected void _processAppModels(String appModelId, String cpModelId, ControlServiceRequestInfo requestInfo) { - log.info("ControlServiceCoordinator._processAppModel(): BEGIN: app-model-id={}, cp-model-id={}, request-info={}", appModelId, cpModelId, requestInfo); + protected void _processAppModels(String appModelId, String appExecModelId, ControlServiceRequestInfo requestInfo) { + log.info("ControlServiceCoordinator._processAppModel(): BEGIN: app-model-id={}, app-exec-model-id={}, request-info={}", appModelId, appExecModelId, requestInfo); // Translate model into Translation Context (with EPL rules etc.) TranslationContext _TC; @@ -298,13 +298,13 @@ public class ControlServiceCoordinator implements InitializingBean { log.error("ControlServiceCoordinator._processAppModel(): EXCEPTION while printing Translation results: ", e); } - // Retrieve Metric Variable Values (MVV) from CP model - i.e. constants - Map constants = new HashMap<>(); + // Retrieve Metric Variable Values (MVV) from App Exec model - i.e. constants + Map constants = new HashMap<>( _TC.getConstantDefaults() ); if (!properties.isSkipMvvRetrieve()) { - if (StringUtils.isNotBlank(cpModelId)) { - constants = retrieveConstantsFromCpModel(cpModelId, _TC, EMS_STATE.INITIALIZING); + if (StringUtils.isNotBlank(appExecModelId)) { + constants.putAll( retrieveConstantsFromAppExecModel(appExecModelId, _TC, EMS_STATE.INITIALIZING) ); } else { - log.warn("ControlServiceCoordinator._processAppModel(): No CP model has been provided"); + log.warn("ControlServiceCoordinator._processAppModel(): No App Exec model has been provided"); } } else { log.warn("ControlServiceCoordinator._processAppModel(): Skipping MVV retrieval due to configuration"); @@ -362,23 +362,23 @@ public class ControlServiceCoordinator implements InitializingBean { setCurrentEmsState(EMS_STATE.READY, null); } - protected void _processCpModel(String cpModelId, ControlServiceRequestInfo requestInfo) { - log.info("ControlServiceCoordinator._processCpModel(): BEGIN: cp-model-id={}, request-info={}", cpModelId, requestInfo); - log.info("ControlServiceCoordinator._processCpModel(): Current app-model-id={}", currentAppModelId); + protected void _processAppExecModel(String appExecModelId, ControlServiceRequestInfo requestInfo) { + log.info("ControlServiceCoordinator._processAppExecModel(): BEGIN: app-exec-model-id={}, request-info={}", appExecModelId, requestInfo); + log.info("ControlServiceCoordinator._processAppExecModel(): Current app-model-id={}", currentAppModelId); TranslationContext _TC = this.currentTC; - // Retrieve Metric Variable Values (MVV) from CP model + // Retrieve Metric Variable Values (MVV) from App Exec model Map constants = new HashMap<>(); if (!properties.isSkipMvvRetrieve()) { - constants = retrieveConstantsFromCpModel(cpModelId, _TC, EMS_STATE.RECONFIGURING); + constants = retrieveConstantsFromAppExecModel(appExecModelId, _TC, EMS_STATE.RECONFIGURING); } else { - log.warn("ControlServiceCoordinator._processCpModel(): Skipping MVV retrieval due to configuration"); + log.warn("ControlServiceCoordinator._processAppExecModel(): Skipping MVV retrieval due to configuration"); } // Set MVV constants in Broker-CEP and Baguette Server, and then notify others _setConstants(constants, requestInfo); - log.info("ControlServiceCoordinator._processCpModel(): END: cp-model-id={}", cpModelId); + log.info("ControlServiceCoordinator._processAppExecModel(): END: app-exec-model-id={}", appExecModelId); setCurrentEmsState(EMS_STATE.READY, null); } @@ -387,7 +387,7 @@ public class ControlServiceCoordinator implements InitializingBean { log.info("ControlServiceCoordinator.setConstants(): BEGIN: constants={}, request-info={}", constants, requestInfo); log.info("ControlServiceCoordinator.setConstants(): constants={}", constants); - // Retrieve Metric Variable Values (MVV) from CP model + // Retrieve Metric Variable Values (MVV) from App Exec model if (properties.isSkipMvvRetrieve()) { log.warn("ControlServiceCoordinator.setConstants(): isSkipMvvRetrieve is true, but constants processing will continue"); } @@ -508,27 +508,27 @@ public class ControlServiceCoordinator implements InitializingBean { private String getTcFileName(@NonNull String appModelId, @NonNull String fileName) { appModelId = StringUtils.removeStart(appModelId, "/"); - return String.format(fileName, appModelId.replaceAll("[^\\p{L}\\d]", "_")); + return fileName.formatted(appModelId.replaceAll("[^\\p{L}\\d]", "_")); } - private Map retrieveConstantsFromCpModel(String cpModelId, TranslationContext _TC, EMS_STATE emsState) { + private Map retrieveConstantsFromAppExecModel(String appExecModelId, TranslationContext _TC, EMS_STATE emsState) { Map constants = Collections.emptyMap(); - if (StringUtils.isNotBlank(cpModelId)) { - setCurrentEmsState(emsState, "Retrieving MVVs from CP model"); + if (StringUtils.isNotBlank(appExecModelId)) { + setCurrentEmsState(emsState, "Retrieving MVVs from App Exec model"); try { - log.debug("ControlServiceCoordinator.retrieveConstantsFromCpModel(): Retrieving MVVs from CP model: cp-model-id={}", cpModelId); + log.debug("ControlServiceCoordinator.retrieveConstantsFromAppExecModel(): Retrieving MVVs from App Exec model: app-exec-model-id={}", appExecModelId); - // Retrieve constant names from '_TC.MVV_CP' and values from a given CP model - log.debug("ControlServiceCoordinator.retrieveConstantsFromCpModel(): Looking for MVV_CP's: {}", _TC.getMvvCP()); - constants = mvvService.getMatchingMetricVariableValues(cpModelId, _TC); - log.debug("ControlServiceCoordinator.retrieveConstantsFromCpModel(): MVVs retrieved from CP model: cp-model-id={}, MVVs={}", cpModelId, constants); + // Retrieve constant names from '_TC.MVV_CP' and values from a given App Exec model + log.debug("ControlServiceCoordinator.retrieveConstantsFromAppExecModel(): Looking for MVV_CP's: {}", _TC.getMvvCP()); + constants = mvvService.getMatchingMetricVariableValues(appExecModelId, _TC); + log.debug("ControlServiceCoordinator.retrieveConstantsFromAppExecModel(): MVVs retrieved from App Exec model: app-exec-model-id={}, MVVs={}", appExecModelId, constants); } catch (Exception ex) { - log.error("ControlServiceCoordinator.retrieveConstantsFromCpModel(): EXCEPTION while retrieving MVVs from CP model: cp-model-id={}", cpModelId, ex); + log.error("ControlServiceCoordinator.retrieveConstantsFromAppExecModel(): EXCEPTION while retrieving MVVs from App Exec model: app-exec-model-id={}", appExecModelId, ex); } } else { - log.error("ControlServiceCoordinator.retrieveConstantsFromCpModel(): No CP model have been provided"); + log.error("ControlServiceCoordinator.retrieveConstantsFromAppExecModel(): No App Exec model have been provided"); } return constants; } diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceRequestInfo.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceRequestInfo.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceRequestInfo.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ControlServiceRequestInfo.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsController.java similarity index 84% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsController.java index fe09e82..28c276a 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsController.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsController.java @@ -21,17 +21,10 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; -import java.util.Optional; - -import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.POST; @Slf4j @RestController @@ -52,8 +45,9 @@ public class CredentialsController { // ------------------------------------------------------------------------------------------------------------ // @PreAuthorize(ROLES_ALLOWED_JWT_TOKEN_OR_API_KEY) - @RequestMapping(value = "/broker/credentials", method = {GET,POST}) - public HttpEntity getBrokerCredentials(@RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) + @GetMapping(value = "/broker/credentials") + public HttpEntity getBrokerCredentials( + @RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) { log.info("CredentialsController.getBrokerCredentials(): BEGIN"); log.trace("CredentialsController.getBrokerCredentials(): JWT token: {}", jwtToken); @@ -78,19 +72,18 @@ public class CredentialsController { } // @PreAuthorize(ROLES_ALLOWED_JWT_TOKEN_OR_API_KEY) - @RequestMapping(value = "/baguette/ref/{ref}", method = {GET,POST}, - produces = MediaType.APPLICATION_JSON_VALUE) - public HttpEntity getNodeCredentials(@PathVariable("ref") Optional optRef, + @GetMapping(value = "/baguette/ref/{ref}", produces = MediaType.APPLICATION_JSON_VALUE) + public HttpEntity getNodeCredentials(@PathVariable String optRef, @RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false) String jwtToken) { log.info("CredentialsController.getNodeCredentials(): BEGIN: ref={}", optRef); log.trace("CredentialsController.getNodeCredentials(): JWT token: {}", jwtToken); - if (StringUtils.isBlank(optRef.orElse(null))) + if (StringUtils.isBlank(optRef)) throw new IllegalArgumentException("The 'ref' parameter is mandatory"); // Check if it is EMS server ref - if (credentialsCoordinator.getReference().equals(optRef.get())) { + if (credentialsCoordinator.getReference().equals(optRef)) { if (coordinator.getBaguetteServer()==null || !coordinator.getBaguetteServer().isServerRunning()) { log.warn("CredentialsController.getNodeCredentials(): Baguette Server is not started"); return null; @@ -108,7 +101,7 @@ public class CredentialsController { } String key = coordinator.getBaguetteServer().getServerPubkey(); - log.debug("CredentialsController.getNodeCredentials(): Retrieved EMS server connection info by reference: ref={}", optRef.get()); + log.debug("CredentialsController.getNodeCredentials(): Retrieved EMS server connection info by reference: ref={}", optRef); // Prepare response Map response = new HashMap<>(); @@ -124,11 +117,11 @@ public class CredentialsController { } // Retrieve node credentials - NodeRegistryEntry entry = coordinator.getBaguetteServer().getNodeRegistry().getNodeByReference(optRef.get()); + NodeRegistryEntry entry = coordinator.getBaguetteServer().getNodeRegistry().getNodeByReference(optRef); if (entry==null) { - throw new IllegalArgumentException("Not found Node with reference: "+optRef.get()); + throw new IllegalArgumentException("Not found Node with reference: "+optRef); } - log.debug("CredentialsController.getNodeCredentials(): Retrieved node by reference: ref={}", optRef.get()); + log.debug("CredentialsController.getNodeCredentials(): Retrieved node by reference: ref={}", optRef); // Prepare response Map response = new HashMap<>(); @@ -148,7 +141,7 @@ public class CredentialsController { // EMS One-Time-Password (OTP) endpoints // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = "/ems/otp/new", method = {GET, POST}) + @GetMapping(value = "/ems/otp/new") public String newOtp() { log.info("CredentialsController.newOtp(): BEGIN"); String newOtp = webSecurityConfig.otpCreate(); @@ -156,7 +149,7 @@ public class CredentialsController { return newOtp; } - @RequestMapping(value = "/ems/otp/remove/{otp}", method = {GET, POST}) + @GetMapping(value = "/ems/otp/remove/{otp}") public String removeOtp(@PathVariable String otp) { log.info("CredentialsController.removeOtp(): BEGIN"); if ("*".equals(otp)) diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsCoordinator.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsCoordinator.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsCoordinator.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/CredentialsCoordinator.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementController.java similarity index 73% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementController.java index 4db8b7e..145876f 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementController.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementController.java @@ -13,19 +13,16 @@ import gr.iccs.imu.ems.control.properties.ControlServiceProperties; import gr.iccs.imu.ems.control.util.TopicBeacon; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import javax.jms.JMSException; +import jakarta.jms.JMSException; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; - -import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.POST; @Slf4j @RestController @@ -40,29 +37,34 @@ public class ManagementController { // Client and Cluster info and control methods // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = "/client/list", method = GET, - produces = MediaType.APPLICATION_JSON_VALUE) + @GetMapping(value = "/client/list", produces = MediaType.APPLICATION_JSON_VALUE) public List listClients() { List clients = coordinator.clientList(); log.info("ManagementController.listClients(): {}", clients); return clients; } - @RequestMapping(value = "/client/list/map", method = GET, - produces = MediaType.APPLICATION_JSON_VALUE) + @GetMapping(value = "/client/list/map", produces = MediaType.APPLICATION_JSON_VALUE) public Map> listClientMaps() { Map> clients = coordinator.clientMap(); log.info("ManagementController.listClientMaps(): {}", clients); return clients; } - @RequestMapping(value = "/client/command/{clientId}/{command:.+}", method = GET) + @GetMapping("/client/command/{clientId}/{command:.+}") public String clientCommand(@PathVariable String clientId, @PathVariable String command) { log.info("ManagementController.clientCommand(): PARAMS: client={}, command={}", clientId, command); return coordinator.clientCommandSend(clientId, command); } - @RequestMapping(value = "/cluster/command/{clusterId}/{command:.+}", method = GET) + @GetMapping({ "/client/stats", "/client/stats/{clientId}" }) + public String clientStats(@PathVariable String clientIdOpt) { + String clientId = StringUtils.defaultIfBlank(clientIdOpt, "*"); + log.info("ManagementController.clientStats(): PARAMS: client={}", clientId); + return coordinator.clientStats(clientId); + } + + @GetMapping("/cluster/command/{clusterId}/{command:.+}") public String clusterCommand(@PathVariable String clusterId, @PathVariable String command) { log.info("ManagementController.clusterCommand(): PARAMS: cluster={}, command={}", clusterId, command); return coordinator.clusterCommandSend(clusterId, command); @@ -72,19 +74,23 @@ public class ManagementController { // Event Generation and Debugging methods // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = "/event/generate-start/{clientId}/{topicName}/{interval}/{lowerValue}/{upperValue}", method = GET) - public String startEventGeneration(@PathVariable String clientId, @PathVariable String topicName, @PathVariable long interval, @PathVariable double lowerValue, @PathVariable double upperValue) { - log.info("ManagementController.startEventGeneration(): PARAMS: client={}, topic={}, interval={}, value-range=[{},{}]", clientId, topicName, interval, lowerValue, upperValue); + @GetMapping("/event/generate-start/{clientId}/{topicName}/{interval}/{lowerValue}/{upperValue}") + public String startEventGeneration(@PathVariable String clientId, @PathVariable String topicName, + @PathVariable long interval, @PathVariable double lowerValue, + @PathVariable double upperValue) + { + log.info("ManagementController.startEventGeneration(): PARAMS: client={}, topic={}, interval={}, value-range=[{},{}]", + clientId, topicName, interval, lowerValue, upperValue); return coordinator.eventGenerationStart(clientId, topicName, interval, lowerValue, upperValue); } - @RequestMapping(value = "/event/generate-stop/{clientId}/{topicName}", method = GET) + @GetMapping("/event/generate-stop/{clientId}/{topicName}") public String stopEventGeneration(@PathVariable String clientId, @PathVariable String topicName) { log.info("ManagementController.stopEventGeneration(): PARAMS: client={}, topic={}", clientId, topicName); return coordinator.eventGenerationStop(clientId, topicName); } - @RequestMapping(value = "/event/send/{clientId}/{topicName}/{value}", method = GET) + @GetMapping("/event/send/{clientId}/{topicName}/{value}") public String sendEvent(@PathVariable String clientId, @PathVariable String topicName, @PathVariable double value) { log.info("ManagementController.sendEvent(): PARAMS: client={}, topic={}, value={}", clientId, topicName, value); return coordinator.eventLocalSend(clientId, topicName, value); @@ -94,17 +100,17 @@ public class ManagementController { // EMS shutdown and exit methods // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = "/ems/shutdown", method = {GET, POST}) + @GetMapping(value = "/ems/shutdown") public String emsShutdown() { log.info("ManagementController.emsShutdown(): Not implemented"); coordinator.emsShutdownServices(); return "OK"; } - @RequestMapping(value = { "/ems/exit", "/ems/exit/{exitCode}" }, method = {GET, POST}) - public String emsExit(@PathVariable Optional exitCode) { + @GetMapping(value = { "/ems/exit", "/ems/exit/{exitCode}" }) + public String emsExit(@PathVariable Integer exitCode) { if (properties.isExitAllowed()) { - int _exitCode = exitCode.orElse(properties.getExitCode()); + int _exitCode = exitCode!=null ? exitCode : properties.getExitCode(); log.info("ManagementController.emsExit(): exitCode={}", _exitCode); coordinator.emsShutdownServices(); coordinator.emsExit(_exitCode); @@ -119,27 +125,28 @@ public class ManagementController { // EMS status and information query methods // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = "/ems/status", method = {GET, POST}, produces = MediaType.APPLICATION_JSON_VALUE) + @GetMapping(value = "/ems/status", produces = MediaType.APPLICATION_JSON_VALUE) public Map emsStatus() { log.info("ManagementController.emsStatus(): Not implemented"); return Collections.emptyMap(); } - @RequestMapping(value = "/ems/topology", method = {GET, POST}, produces = MediaType.APPLICATION_JSON_VALUE) + @GetMapping(value = "/ems/topology", produces = MediaType.APPLICATION_JSON_VALUE) public Map emsTopology() { log.info("ManagementController.emsTopology(): Not implemented"); return Collections.emptyMap(); } - @RequestMapping(value = { "/beacon", "/beacon/transmit" }, method = GET) + @GetMapping({ "/beacon", "/beacon/transmit" }) public void beaconTransmit() throws JMSException { log.info("ManagementController.beaconTransmit(): Invoked"); + coordinator.clientStats("*"); topicBeacon.transmitInfo(); } // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = "/health", method = GET) + @GetMapping("/health") public String health() { return "OK"; } diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementCoordinator.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementCoordinator.java similarity index 98% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementCoordinator.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementCoordinator.java index 6ee9d52..cb3cc7e 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementCoordinator.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/ManagementCoordinator.java @@ -219,4 +219,9 @@ public class ManagementCoordinator { // Log success return eventLogEnd(method, EVENT_LOG_OK); } + + public String clientStats(String clientId) { + String command = "COLLECT-STATS"; + return clientCommandSend(clientId, command); + } } diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationController.java similarity index 67% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationController.java index c98a7a3..5ca14d4 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationController.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationController.java @@ -13,28 +13,21 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import gr.iccs.imu.ems.baguette.server.BaguetteServer; import gr.iccs.imu.ems.baguette.server.NodeRegistryEntry; -import gr.iccs.imu.ems.control.properties.ControlServiceProperties; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.lang.reflect.Type; import java.util.Collection; import java.util.Map; -import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.POST; - @Slf4j @RestController @RequiredArgsConstructor public class NodeRegistrationController { - private final ControlServiceProperties properties; private final ControlServiceCoordinator coordinator; private final NodeRegistrationCoordinator nodeRegistrationCoordinator; @@ -42,7 +35,7 @@ public class NodeRegistrationController { // Baguette control methods // ------------------------------------------------------------------------------------------------------------ - @RequestMapping(value = "/baguette/stopServer", method = {GET, POST}) + @GetMapping("/baguette/stopServer") public String baguetteStopServer() { log.info("NodeRegistrationController.baguetteStopServer(): Request received"); @@ -53,9 +46,9 @@ public class NodeRegistrationController { return "OK"; } - @RequestMapping(value = { "/baguette/registerNode", "/baguette/node/register" }, method = POST, + @PostMapping(value = { "/baguette/registerNode", "/baguette/node/register" }, consumes = MediaType.APPLICATION_JSON_VALUE) - public String baguetteRegisterNode(@RequestBody String jsonNode, HttpServletRequest request) throws Exception { + public String baguetteRegisterNode(@RequestBody String jsonNode, HttpServletRequest request) { log.info("NodeRegistrationController.baguetteRegisterNode(): Invoked"); log.debug("NodeRegistrationController.baguetteRegisterNode(): Node json:\n{}", jsonNode); @@ -71,7 +64,8 @@ public class NodeRegistrationController { response = nodeRegistrationCoordinator.registerNode(request, nodeMap, coordinator.getTranslationContextOfAppModel(coordinator.getCurrentAppModelId())); } catch (Exception e) { - log.error("NodeRegistrationController.baguetteRegisterNode(): EXCEPTION while registering node: map={}\n", nodeMap, e); + log.error("NodeRegistrationController.baguetteRegisterNode(): EXCEPTION while registering node: map={}\n", + nodeMap, e); response = "ERROR "+e.getMessage(); } @@ -80,9 +74,8 @@ public class NodeRegistrationController { return response; } - @RequestMapping(value = "/baguette/node/unregister/{ipAddress:.+}", method = {GET, POST}, - produces = MediaType.TEXT_PLAIN_VALUE) - public String baguetteUnregisterNode(@PathVariable String ipAddress, HttpServletRequest request) throws Exception { + @GetMapping(value = "/baguette/node/unregister/{ipAddress:.+}", produces = MediaType.TEXT_PLAIN_VALUE) + public String baguetteUnregisterNode(@PathVariable String ipAddress, HttpServletRequest request) { log.info("NodeRegistrationController.baguetteUnregisterNode(): Invoked"); log.debug("NodeRegistrationController.baguetteUnregisterNode(): Node IP address:\n{}", ipAddress); @@ -100,8 +93,8 @@ public class NodeRegistrationController { return response; } - @RequestMapping(value = "/baguette/node/list", method = GET) - public Collection baguetteNodeList() throws Exception { + @GetMapping("/baguette/node/list") + public Collection baguetteNodeList() { log.info("NodeRegistrationController.baguetteNodeList(): Invoked"); Collection addresses = coordinator.getBaguetteServer().getNodeRegistry().getNodeAddresses(); @@ -110,39 +103,25 @@ public class NodeRegistrationController { return addresses; } - @RequestMapping(value = "/baguette/node/reinstall/{ipAddress:.+}", method = {GET, POST}, - produces = MediaType.TEXT_PLAIN_VALUE) + @GetMapping(value = "/baguette/node/reinstall/{ipAddress:.+}", produces = MediaType.TEXT_PLAIN_VALUE) public String baguetteNodeReinstall(@PathVariable String ipAddress) throws Exception { log.info("NodeRegistrationController.baguetteNodeReinstall(): Invoked"); log.info("NodeRegistrationController.baguetteNodeReinstall(): Node IP address: {}", ipAddress); - // Get node info using IP address - BaguetteServer baguette = coordinator.getBaguetteServer(); - NodeRegistryEntry nodeInfo = baguette.getNodeRegistry().getNodeByAddress(ipAddress); - log.info("NodeRegistrationController.baguetteNodeReinstall(): Info for node at: ip-address={}, Node Info:\n{}", - ipAddress, nodeInfo); - if (nodeInfo==null) { - log.warn("NodeRegistrationController.baguetteNodeReinstall(): Not found pre-registered node with ip-address: {}", ipAddress); - return "NODE NOT FOUND: "+ipAddress; + if (StringUtils.isBlank(ipAddress)) { + log.warn("NodeRegistrationController.baguetteNodeReinstall(): IP address is blank: {}", ipAddress); + return "ERROR: Blank IP address"; } - // Continue processing according to ExecutionWare type - String response; - log.info("NodeRegistrationController.baguetteNodeReinstall(): ExecutionWare: {}", properties.getExecutionware()); - if (properties.getExecutionware() == ControlServiceProperties.ExecutionWare.CLOUDIATOR) { - response = nodeRegistrationCoordinator.getClientInstallationInstructions(nodeInfo); - } else { - response = nodeRegistrationCoordinator.createClientInstallationTask(nodeInfo, - coordinator.getTranslationContextOfAppModel(coordinator.getCurrentAppModelId())); - } + String response = nodeRegistrationCoordinator.reinstallNode(ipAddress, + coordinator.getTranslationContextOfAppModel(coordinator.getCurrentAppModelId())); - log.info("NodeRegistrationController.baguetteNodeReinstall(): node ip-address: {}, response: {}", ipAddress, response); + log.info("NodeRegistrationController.baguetteNodeReinstall(): Node reinstall response: ip-address: {}, response: {}", ipAddress, response); return response; } - @RequestMapping(value = "/baguette/getNodeInfoByAddress/{ipAddress:.+}", method = {GET, POST}, - produces = MediaType.APPLICATION_JSON_VALUE) - public NodeRegistryEntry baguetteGetNodeInfoByAddress(@PathVariable String ipAddress) throws Exception { + @GetMapping(value = "/baguette/getNodeInfoByAddress/{ipAddress:.+}", produces = MediaType.APPLICATION_JSON_VALUE) + public NodeRegistryEntry baguetteGetNodeInfoByAddress(@PathVariable String ipAddress) { log.info("NodeRegistrationController.baguetteGetNodeInfoByAddress(): ip-address={}", ipAddress); BaguetteServer baguette = coordinator.getBaguetteServer(); @@ -153,9 +132,8 @@ public class NodeRegistrationController { return nodeInfo; } - @RequestMapping(value = "/baguette/getNodeNameByAddress/{ipAddress:.+}", method = {GET, POST}, - produces = MediaType.TEXT_PLAIN_VALUE) - public String baguetteGetNodeNameByAddress(@PathVariable String ipAddress) throws Exception { + @GetMapping(value = "/baguette/getNodeNameByAddress/{ipAddress:.+}", produces = MediaType.TEXT_PLAIN_VALUE) + public String baguetteGetNodeNameByAddress(@PathVariable String ipAddress) { log.info("NodeRegistrationController.baguetteGetNodeNameByAddress(): ip-address={}", ipAddress); BaguetteServer baguette = coordinator.getBaguetteServer(); diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationCoordinator.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationCoordinator.java similarity index 84% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationCoordinator.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationCoordinator.java index bf5cdad..6eb8899 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationCoordinator.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/NodeRegistrationCoordinator.java @@ -115,6 +115,10 @@ public class NodeRegistrationCoordinator implements InitializingBean { updateRegistrationInfo(nodeMapFlattened, baseUrl); log.trace("NodeRegistrationCoordinator.registerNode(): updated flattened node info map: \n{}", nodeMapFlattened); + // Update node registration info with APP_ID, APP_NAME, MODEL_NAME, and MODEL_FILE_NAME + updateTranslationInfo(nodeMapFlattened, translationContext); + log.trace("NodeRegistrationCoordinator.registerNode(): updated flattened node info map: \n{}", nodeMapFlattened); + // Register node to Baguette server NodeRegistryEntry entry; try { @@ -191,6 +195,27 @@ public class NodeRegistrationCoordinator implements InitializingBean { return response; } + public String reinstallNode(String ipAddress, TranslationContext translationContext) throws Exception { + // Get node info using IP address + NodeRegistryEntry nodeInfo = baguetteServer.getNodeRegistry().getNodeByAddress(ipAddress); + log.info("NodeRegistrationCoordinator.reinstallNode(): Info for node at: ip-address={}, Node Info:\n{}", + ipAddress, nodeInfo); + if (nodeInfo==null) { + log.warn("NodeRegistrationCoordinator.reinstallNode(): Not found pre-registered node with ip-address: {}", ipAddress); + return "NODE NOT FOUND: "+ipAddress; + } + + // Continue processing according to ExecutionWare type + String response; + log.info("NodeRegistrationCoordinator.reinstallNode(): ExecutionWare: {}", properties.getExecutionware()); + if (properties.getExecutionware() == ControlServiceProperties.ExecutionWare.CLOUDIATOR) { + response = getClientInstallationInstructions(nodeInfo); + } else { + response = createClientReinstallTask(nodeInfo, translationContext); + } + return response; + } + void updateRegistrationInfo(Map nodeMap, String baseUrl) { // Set OS info String os = StringUtils.isNotBlank(nodeMap.get("operatingSystem.name")) @@ -208,6 +233,14 @@ public class NodeRegistrationCoordinator implements InitializingBean { nodeMap.put("IP_SETTING", ipSetting); } + void updateTranslationInfo(Map nodeMap, TranslationContext translationContext) { + // Add model and application info + nodeMap.put("TC_MODEL_NAME", StringUtils.defaultIfBlank(translationContext.getModelName(), "")); + nodeMap.put("TC_MODEL_FILE_NAME", StringUtils.defaultIfBlank(translationContext.getModelFileName(), "")); + nodeMap.put("TC_APP_ID", StringUtils.defaultIfBlank(translationContext.getAppId(), "")); + nodeMap.put("TC_APP_NAME", StringUtils.defaultIfBlank(translationContext.getAppName(), "")); + } + public String getServerIpAddress() { return (properties.getIpSetting() == ControlServiceProperties.IpSetting.DEFAULT_IP) ? NetUtil.getDefaultIpAddress() @@ -286,6 +319,21 @@ public class NodeRegistrationCoordinator implements InitializingBean { return "OK"; } + public String createClientReinstallTask(NodeRegistryEntry entry, TranslationContext translationContext) throws Exception { + return createClientReinstallTask(entry, translationContext, null); + } + + public String createClientReinstallTask(NodeRegistryEntry entry, TranslationContext translationContext, Callable callback) throws Exception { + ClientInstallationTask reinstallTask = InstallationHelperFactory.getInstance() + .createInstallationHelper(entry) + .createClientReinstallTask(entry, translationContext); + reinstallTask.setCallback(callback); + ClientInstaller.instance().addTask(reinstallTask); + log.debug("NodeRegistrationCoordinator.createClientReinstallTask(): New reinstall-task: {}", reinstallTask); + + return "OK"; + } + public String createClientUninstallTask(NodeRegistryEntry entry, TranslationContext translationContext) throws Exception { return createClientUninstallTask(entry, translationContext, null); } diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerException.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerException.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerException.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerException.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerExceptionHandler.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerExceptionHandler.java similarity index 91% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerExceptionHandler.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerExceptionHandler.java index 2fc2320..cfa79e7 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerExceptionHandler.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/controller/RestControllerExceptionHandler.java @@ -15,7 +15,9 @@ import lombok.Data; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.InitializingBean; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -50,8 +52,10 @@ public class RestControllerExceptionHandler extends ResponseEntityExceptionHandl } // Return error response + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); ErrorType error = new ErrorType(httpStatus, ex); - return new ResponseEntity<>(error, error.getReason()); + return new ResponseEntity<>(error, headers, error.getReason()); } @Data diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/BuildInfoProvider.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/BuildInfoProvider.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/BuildInfoProvider.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/BuildInfoProvider.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceBuildInfoEndpoint.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceBuildInfoEndpoint.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceBuildInfoEndpoint.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceBuildInfoEndpoint.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceHealthIndicator.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceHealthIndicator.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceHealthIndicator.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceHealthIndicator.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceInfoEndpointExtension.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceInfoEndpointExtension.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceInfoEndpointExtension.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceInfoEndpointExtension.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceLiveInfoEndpoint.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceLiveInfoEndpoint.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceLiveInfoEndpoint.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceLiveInfoEndpoint.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMBean.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMBean.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMBean.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMBean.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMetrics.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMetrics.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMetrics.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/ControlServiceMetrics.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/EmsInfoServiceImpl.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/EmsInfoServiceImpl.java similarity index 99% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/EmsInfoServiceImpl.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/EmsInfoServiceImpl.java index f03e704..d8bba6c 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/EmsInfoServiceImpl.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/EmsInfoServiceImpl.java @@ -158,8 +158,8 @@ public class EmsInfoServiceImpl implements IEmsInfoService { controlServiceInfo.put("current-ems-state", controlServiceCoordinator.getCurrentEmsState()); controlServiceInfo.put("current-ems-state-message", controlServiceCoordinator.getCurrentEmsStateMessage()); controlServiceInfo.put("current-ems-state-change-timestamp", controlServiceCoordinator.getCurrentEmsStateChangeTimestamp()); - controlServiceInfo.put("current-app-model-path", controlServiceCoordinator.getAppModelPath()); - controlServiceInfo.put("current-cp-model-path", controlServiceCoordinator.getCpModelPath()); + controlServiceInfo.put("current-app-model-path", controlServiceCoordinator.getAppModelId()); + controlServiceInfo.put("current-app-exec-model-path", controlServiceCoordinator.getAppExecModelId()); if (controlServiceProperties!=null && infoServiceProperties!=null) { controlServiceInfo.put("prop-ip-setting", controlServiceProperties.getIpSetting()); controlServiceInfo.put("prop-executionware", controlServiceProperties.getExecutionware().toString()); @@ -226,7 +226,7 @@ public class EmsInfoServiceImpl implements IEmsInfoService { // Destinations per grouping and min/max grouping Map translatorInfo = new LinkedHashMap<>(); metrics.put(TRANSLATOR_INFO_PROVIDER, translatorInfo); - String appModelPath = controlServiceCoordinator.getAppModelPath(); + String appModelPath = controlServiceCoordinator.getAppModelId(); if (StringUtils.isNotBlank(appModelPath)) { TranslationContext _TC = controlServiceCoordinator.getTranslationContextOfAppModel(appModelPath); Set groupings = _TC.getG2T().keySet(); diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesController.java similarity index 99% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesController.java index 154285f..c611164 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesController.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesController.java @@ -31,7 +31,7 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.HandlerMapping; -import javax.validation.constraints.Null; +import jakarta.validation.constraints.Null; import java.io.*; import java.net.URLConnection; import java.nio.file.Files; diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesDisabledController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesDisabledController.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesDisabledController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/FilesDisabledController.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoProvider.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoProvider.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoProvider.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoProvider.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoService.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoService.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoService.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/IEmsInfoService.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/InfoServiceController.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/InfoServiceController.java similarity index 95% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/InfoServiceController.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/InfoServiceController.java index 7c7a4c4..decf925 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/InfoServiceController.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/InfoServiceController.java @@ -118,7 +118,7 @@ public class InfoServiceController implements InitializingBean { @GetMapping("/info/client-metrics/get/{clientIds}") public Mono> clientMetricsGet( - @PathVariable("clientIds") List clientIds, HttpServletRequest request) + @PathVariable List clientIds, HttpServletRequest request) { log.info("clientMetricsGet(): baguette-client-ids={} --- client: {}:{}", clientIds, request.getRemoteAddr(), request.getRemotePort()); Map message = createClientMetricsResult(null, -1L, clientIds); @@ -128,14 +128,14 @@ public class InfoServiceController implements InitializingBean { @GetMapping("/info/client-metrics/stream/{clientIds}") public Flux>> clientMetricsStream( - @PathVariable("clientIds") List clientIds, - @QueryParam("interval") Optional interval, + @PathVariable List clientIds, + @QueryParam("interval") Integer interval, HttpServletRequest request) { String sid = UUID.randomUUID().toString(); log.info("clientMetricsStream(): interval={}, baguette-client-ids={} --- client: {}:{}, Stream-Id: {}", interval, clientIds, request.getRemoteAddr(), request.getRemotePort(), sid); - int intervalInSeconds = interval.orElse(-1); + int intervalInSeconds = interval!=null ? interval : -1; if (intervalInSeconds<1) intervalInSeconds = properties.getMetricsStreamUpdateInterval(); log.debug("clientMetricsStream(): effective-interval={}", intervalInSeconds); @@ -153,7 +153,7 @@ public class InfoServiceController implements InitializingBean { } @GetMapping("/info/client-metrics/clear/{clientIds}") - public String clientMetricsClear(@PathVariable("clientIds") List clientIds, HttpServletRequest request) { + public String clientMetricsClear(@PathVariable List clientIds, HttpServletRequest request) { log.info("clientMetricsClear(): baguette-client-ids={} --- client: {}:{}", clientIds, request.getRemoteAddr(), request.getRemotePort()); emsInfoService.clearClientMetricValues(); @@ -164,9 +164,10 @@ public class InfoServiceController implements InitializingBean { @GetMapping("/info/all-metrics/get/{clientIds}") public Mono> allMetricsGet( - @PathVariable("clientIds") List clientIds, HttpServletRequest request, @AuthenticationPrincipal UserDetails user) + @PathVariable List clientIds, HttpServletRequest request, @AuthenticationPrincipal UserDetails user) { - log.info("allMetricsGet(): baguette-client-ids={} --- client: {}:{}", clientIds, request.getRemoteAddr(), request.getRemotePort()); + log.info("allMetricsGet(): baguette-client-ids={} --- client: {}:{}", + clientIds, request.getRemoteAddr(), request.getRemotePort()); Map message1 = createServerMetricsResult(null, -1L, user); Map message2 = createClientMetricsResult(null, -1L, clientIds); Map message = new LinkedHashMap<>(); @@ -178,15 +179,15 @@ public class InfoServiceController implements InitializingBean { @GetMapping("/info/all-metrics/stream/{clientIds}") public Flux>> allMetricsStream( - @PathVariable("clientIds") List clientIds, - @QueryParam("interval") Optional interval, + @PathVariable List clientIds, + @QueryParam("interval") Integer interval, HttpServletRequest request, @AuthenticationPrincipal UserDetails user) { String sid = UUID.randomUUID().toString(); log.info("allMetricsStream(): interval={}, baguette-client-ids={} --- client: {}:{}, Stream-Id: {}", interval, clientIds, request.getRemoteAddr(), request.getRemotePort(), sid); - int intervalInSeconds = interval.orElse(-1); + int intervalInSeconds = interval!=null ? interval : -1; if (intervalInSeconds<1) intervalInSeconds = properties.getMetricsStreamUpdateInterval(); log.debug("allMetricsStream(): effective-interval={}", intervalInSeconds); diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/SystemInfoProvider.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/SystemInfoProvider.java similarity index 89% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/SystemInfoProvider.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/SystemInfoProvider.java index 6e824c1..1037847 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/SystemInfoProvider.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/info/SystemInfoProvider.java @@ -46,12 +46,12 @@ public class SystemInfoProvider implements IEmsInfoProvider { RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); long uptime = runtimeBean.getUptime() / 1000; - String vmInfo = String.format("%s, ver.%s, by %s", runtimeBean.getVmName(), runtimeBean.getVmVersion(), runtimeBean.getVmVendor()); + String vmInfo = "%s, ver.%s, by %s".formatted(runtimeBean.getVmName(), runtimeBean.getVmVersion(), runtimeBean.getVmVendor()); sysInfo.put("jvm-info", vmInfo); sysInfo.put("jvm-uptime", uptime); OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); - String osInfo = String.format("OS %s, %s, v.%s, processors: %d, avg. load: %.02f", osBean.getName(), osBean.getArch(), osBean.getVersion(), + String osInfo = "OS %s, %s, v.%s, processors: %d, avg. load: %.02f".formatted(osBean.getName(), osBean.getArch(), osBean.getVersion(), osBean.getAvailableProcessors(), osBean.getSystemLoadAverage()); sysInfo.put("os-info", osInfo); diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/BeaconPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/BeaconPlugin.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/BeaconPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/BeaconPlugin.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/EmsInfoPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/EmsInfoPlugin.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/EmsInfoPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/EmsInfoPlugin.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/MetasolverPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/MetasolverPlugin.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/MetasolverPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/MetasolverPlugin.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/PostTranslationPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/PostTranslationPlugin.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/PostTranslationPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/PostTranslationPlugin.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/TranslationContextPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/TranslationContextPlugin.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/TranslationContextPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/TranslationContextPlugin.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/WebAdminPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/WebAdminPlugin.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/WebAdminPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/WebAdminPlugin.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopBeaconPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopBeaconPlugin.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopBeaconPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopBeaconPlugin.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopPostTranslationPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopPostTranslationPlugin.java similarity index 96% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopPostTranslationPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopPostTranslationPlugin.java index 06a2d51..13a7dab 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopPostTranslationPlugin.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopPostTranslationPlugin.java @@ -12,11 +12,10 @@ package gr.iccs.imu.ems.control.plugin.noop; import gr.iccs.imu.ems.control.plugin.PostTranslationPlugin; import gr.iccs.imu.ems.control.util.TopicBeacon; import gr.iccs.imu.ems.translate.TranslationContext; +import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import javax.annotation.PostConstruct; - @Slf4j @Service public class NoopPostTranslationPlugin implements PostTranslationPlugin { diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopTranslationContextPlugin.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopTranslationContextPlugin.java similarity index 96% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopTranslationContextPlugin.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopTranslationContextPlugin.java index d2b9dc8..bb80ac5 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopTranslationContextPlugin.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/plugin/noop/NoopTranslationContextPlugin.java @@ -11,11 +11,10 @@ package gr.iccs.imu.ems.control.plugin.noop; import gr.iccs.imu.ems.control.plugin.TranslationContextPlugin; import gr.iccs.imu.ems.translate.TranslationContext; +import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import javax.annotation.PostConstruct; - @Slf4j @Service public class NoopTranslationContextPlugin implements TranslationContextPlugin { diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/ControlServiceProperties.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/ControlServiceProperties.java similarity index 98% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/ControlServiceProperties.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/ControlServiceProperties.java index 39e568a..1ccd452 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/ControlServiceProperties.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/ControlServiceProperties.java @@ -18,7 +18,7 @@ import org.springframework.context.annotation.Configuration; //import org.springframework.context.annotation.PropertySource; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.Min; +import jakarta.validation.constraints.Min; import static gr.iccs.imu.ems.util.EmsConstant.EMS_PROPERTIES_PREFIX; diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/InfoServiceProperties.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/InfoServiceProperties.java similarity index 96% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/InfoServiceProperties.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/InfoServiceProperties.java index e2d1c43..5bf032e 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/InfoServiceProperties.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/InfoServiceProperties.java @@ -18,8 +18,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/StaticResourceProperties.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/StaticResourceProperties.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/StaticResourceProperties.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/StaticResourceProperties.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/TopicBeaconProperties.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/TopicBeaconProperties.java similarity index 97% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/TopicBeaconProperties.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/TopicBeaconProperties.java index 8e47621..0f2370d 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/TopicBeaconProperties.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/TopicBeaconProperties.java @@ -17,7 +17,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.Min; +import jakarta.validation.constraints.Min; import java.util.HashSet; import java.util.Set; diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/WebSecurityProperties.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/WebSecurityProperties.java similarity index 91% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/WebSecurityProperties.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/WebSecurityProperties.java index a4b597d..dedd45a 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/WebSecurityProperties.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/properties/WebSecurityProperties.java @@ -17,9 +17,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.validation.annotation.Validated; -import javax.validation.Valid; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import java.util.Arrays; import java.util.List; @@ -95,5 +95,6 @@ public class WebSecurityProperties implements InitializingBean { // Permitted URLs private List permittedUrls = Arrays.asList( - "/login*", "/logout*", "/favicon.ico", "/admin/login.html", "/admin/favicon.ico", "/admin/assets/**", "/resources/*"); + "/login*", "/logout*", "/admin/login.html", "/favicon.ico", "/admin/favicon.ico", + "/admin/assets/**", "/resources/*", "/health"); } diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/EventBusCache.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/EventBusCache.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/EventBusCache.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/EventBusCache.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/NodeRegistrationHelper.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/NodeRegistrationHelper.java similarity index 62% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/NodeRegistrationHelper.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/NodeRegistrationHelper.java index fe7d7fa..83e36e4 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/NodeRegistrationHelper.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/NodeRegistrationHelper.java @@ -10,6 +10,9 @@ package gr.iccs.imu.ems.control.util; import gr.iccs.imu.ems.baguette.client.install.api.INodeRegistration; +import gr.iccs.imu.ems.baguette.server.NodeRegistry; +import gr.iccs.imu.ems.baguette.server.NodeRegistryEntry; +import gr.iccs.imu.ems.control.controller.ManagementCoordinator; import gr.iccs.imu.ems.control.controller.NodeRegistrationCoordinator; import gr.iccs.imu.ems.translate.TranslationContext; import lombok.RequiredArgsConstructor; @@ -24,6 +27,9 @@ import java.util.Map; @RequiredArgsConstructor public class NodeRegistrationHelper implements InitializingBean, INodeRegistration { private final NodeRegistrationCoordinator nodeRegistrationCoordinator; + private final ManagementCoordinator managementCoordinator; + private final NodeRegistry nodeRegistry; + private final TopicBeacon topicBeacon; @Override public void afterPropertiesSet() throws Exception { @@ -37,10 +43,30 @@ public class NodeRegistrationHelper implements InitializingBean, INodeRegistrati return nodeRegistrationCoordinator.registerNode(baseUrl, nodeInfo, translationContext); } + @Override + public String reinstallNode(String ipAddress, TranslationContext translationContext) throws Exception { + log.debug("NodeRegistrationHelper: Invoking reinstallNode: baseUrl={}, TC={}", + ipAddress, translationContext); + return nodeRegistrationCoordinator.reinstallNode(ipAddress, translationContext); + } + @Override public String unregisterNode(String nodeAddress, TranslationContext translationContext) throws Exception { log.debug("NodeRegistrationHelper: Invoking unregisterNode: node-address={}, TC={}", nodeAddress, translationContext); return nodeRegistrationCoordinator.unregisterNode(nodeAddress, translationContext); } + + @Override + public NodeRegistryEntry requestNodeDetails(String nodeAddress) throws Exception { + log.debug("NodeRegistrationHelper: Invoking nodeDetails: node-address={}", nodeAddress); + return nodeRegistry.getNodeByAddress(nodeAddress); + } + + @Override + public void requestInfo() throws Exception { + log.info("NodeRegistrationHelper: Invoking transmitInfo"); + managementCoordinator.clientStats("*"); + topicBeacon.transmitInfo(); + } } diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TopicBeacon.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TopicBeacon.java similarity index 89% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TopicBeacon.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TopicBeacon.java index 6e6b434..87cbc97 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TopicBeacon.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TopicBeacon.java @@ -21,6 +21,7 @@ import gr.iccs.imu.ems.control.controller.ControlServiceCoordinator; import gr.iccs.imu.ems.control.plugin.BeaconPlugin; import gr.iccs.imu.ems.control.properties.TopicBeaconProperties; import gr.iccs.imu.ems.translate.TranslationContext; +import jakarta.jms.JMSException; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -30,7 +31,6 @@ import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Service; -import javax.jms.JMSException; import java.io.IOException; import java.io.Serializable; import java.time.Duration; @@ -184,7 +184,8 @@ public class TopicBeacon implements InitializingBean { .getMetricConstraints() .forEach(c -> { String message = gson.toJson(c); - log.debug("Topic Beacon: Transmitting Metric Constraint threshold info: message={}, topics={}",message, properties.getThresholdTopics()); + log.debug("Topic Beacon: Transmitting Metric Constraint threshold info: message={}, topics={}", + message, properties.getThresholdTopics()); try { sendEventToTopics(message, properties.getThresholdTopics()); } catch (JMSException e) { @@ -214,16 +215,32 @@ public class TopicBeacon implements InitializingBean { } public void transmitBasicMetrics() { + log.trace("Topic Beacon: transmitBasicMetrics: BEGIN: topics={}", properties.getBasicMetricsTopics()); if (emptyIfNull(properties.getBasicMetricsTopics()).isEmpty()) return; + log.trace("Topic Beacon: transmitBasicMetrics: Baguette Server is running: {}", coordinator.getBaguetteServer().isServerRunning()); if (coordinator.getBaguetteServer().isServerRunning()) { + log.trace("Topic Beacon: transmitBasicMetrics: Num of Active CSC's: {}", ClientShellCommand.getActive()); for (ClientShellCommand csc : ClientShellCommand.getActive()) { + // Get client id and address + String clientId = csc.getClientId(); + String clientIpAddress = csc.getClientIpAddress(); + log.debug("Topic Beacon: transmitBasicMetrics: Processing CSC: client-id={}, ip-address={}", clientId, clientIpAddress); + if (StringUtils.isBlank(clientId) || StringUtils.isBlank(clientIpAddress)) { + log.error("Topic Beacon: Ignoring CSC without Id or IP address: {}", csc); + continue; + } + + // Get client statistics Map stats = csc.getClientStatistics(); + log.debug("Topic Beacon: transmitBasicMetrics: CSC statistics: client-id={}, ip-address={}, stats={}", clientId, clientIpAddress, stats); + if (stats==null) { + log.debug("Topic Beacon: No metrics for: instance={}, ip-address={}", clientId, clientIpAddress); + continue; + } + + // Transmit client statistics try { - String clientId = csc.getClientId(); - String clientIpAddress = csc.getClientIpAddress(); - if (StringUtils.isBlank(clientId) || StringUtils.isBlank(clientIpAddress)) - continue; long timestamp = Long.parseLong(StringUtils.defaultIfBlank( stats.getOrDefault("_received_at_server_timestamp", "").toString().trim(), "-1" @@ -232,7 +249,7 @@ public class TopicBeacon implements InitializingBean { stats.put("ipAddress", clientIpAddress); stats.put("receivedAtServer", Instant.ofEpochMilli(timestamp).toString()); log.debug("Topic Beacon: Transmitting Basic Metrics for: instance={}, ip-address={}, message={}, topics={}", - clientId, clientIpAddress, stats, properties.getInstanceTopics()); + clientId, clientIpAddress, stats, properties.getBasicMetricsTopics()); sendEventToTopics(stats, properties.getBasicMetricsTopics()); } catch (Exception e) { log.error("Topic Beacon: Transmitting Basic Metrics for: EXCEPTION while preparing basic metrics for client: id={}, ip-address={}, metrics={}\n", @@ -240,6 +257,7 @@ public class TopicBeacon implements InitializingBean { } } } + log.trace("Topic Beacon: transmitBasicMetrics: END"); } // ------------------------------------------------------------------------ diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TranslationContextMonitorGsonDeserializer.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TranslationContextMonitorGsonDeserializer.java similarity index 93% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TranslationContextMonitorGsonDeserializer.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TranslationContextMonitorGsonDeserializer.java index aeb7b5a..6456325 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TranslationContextMonitorGsonDeserializer.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/TranslationContextMonitorGsonDeserializer.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; @Slf4j public class TranslationContextMonitorGsonDeserializer implements JsonDeserializer { @@ -66,15 +67,20 @@ public class TranslationContextMonitorGsonDeserializer implements JsonDeserializ pullSensor.setClassName(className); } - pullSensor.setConfiguration( getConfiguration(jsonSensorObject, metricName, componentName, "PullSensor") ); - pullSensor.setInterval( getInterval(jsonSensorObject, metricName, componentName, "PullSensor") ); + pullSensor.setConfiguration( castToMapStringObject( + getConfiguration(jsonSensorObject, metricName, componentName, "PullSensor") ) ); + sensor = pullSensor; } else if (isPush) { PushSensor pushSensor = new PushSensor(); int port = jsonSensorObject.getAsJsonPrimitive("port").getAsInt(); pushSensor.setPort(port); + + pushSensor.setConfiguration( castToMapStringObject( + getConfiguration(jsonSensorObject, metricName, componentName, "PushSensor") ) ); + sensor = pushSensor; } else { throw new JsonParseException("Monitor.Sensor is neither Pull or Push: " @@ -141,6 +147,12 @@ public class TranslationContextMonitorGsonDeserializer implements JsonDeserializ return configPairs; } + public Map castToMapStringObject(Map m) { + return m.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, Map.Entry::getValue + )); + } + public Interval getInterval(JsonObject jsonObject, String metricName, String componentName, String field) { if (!jsonObject.has("interval")) return null; if (jsonObject.get("interval").isJsonNull()) return null; diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/WebClientUtil.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/WebClientUtil.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/WebClientUtil.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/WebClientUtil.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenProperties.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenProperties.java similarity index 93% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenProperties.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenProperties.java index ba95937..e3142b5 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenProperties.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenProperties.java @@ -18,8 +18,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import java.time.Duration; @Slf4j diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenService.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenService.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenService.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenService.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenUtil.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenUtil.java similarity index 98% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenUtil.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenUtil.java index 6a1c559..e8d12c5 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenUtil.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/jwt/JwtTokenUtil.java @@ -21,11 +21,11 @@ import org.springframework.context.annotation.ComponentScan; /** * Run: - * java -cp .\target\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR org.springframework.boot.loader.PropertiesLauncher createKey + * java -cp .\target\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR org.springframework.boot.loader.launch.PropertiesLauncher createKey * -or- - * java -cp .\target\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR org.springframework.boot.loader.PropertiesLauncher create [USER]? + * java -cp .\target\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR org.springframework.boot.loader.launch.PropertiesLauncher create [USER]? * -or- - * java -cp .\target\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR org.springframework.boot.loader.PropertiesLauncher parser [TOKEN] + * java -cp .\target\control-service.jar -Dloader.main=jwt.util.gr.iccs.imu.ems.control.JwtTokenUtil -Dlogging.level.ROOT=WARN -Dlogging.level.gr.iccs.imu.ems.util=ERROR org.springframework.boot.loader.launch.PropertiesLauncher parser [TOKEN] */ @Slf4j @SpringBootApplication diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/mvv/NoopMetricVariableValuesServiceImpl.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/mvv/NoopMetricVariableValuesServiceImpl.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/mvv/NoopMetricVariableValuesServiceImpl.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/util/mvv/NoopMetricVariableValuesServiceImpl.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/StaticResourceConfiguration.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/StaticResourceConfiguration.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/StaticResourceConfiguration.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/StaticResourceConfiguration.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebMvcConfig.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebMvcConfig.java similarity index 100% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebMvcConfig.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebMvcConfig.java diff --git a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebSecurityConfig.java b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebSecurityConfig.java similarity index 98% rename from ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebSecurityConfig.java rename to nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebSecurityConfig.java index c16bb6c..d1ce3cb 100644 --- a/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebSecurityConfig.java +++ b/nebulous/ems-core/control-service/src/main/java/gr/iccs/imu/ems/control/webconf/WebSecurityConfig.java @@ -161,7 +161,7 @@ public class WebSecurityConfig implements InitializingBean { throw new InvalidParameterException("User form authentication is enabled but username or password is blank"); if (securityEnabled && apiKeyAuthEnabled && StringUtils.isBlank(apiKeyValue)) throw new InvalidParameterException("API Key authentication is enabled but no API Key provided or it is blank"); - if (permittedUrls==null) permittedUrls = new String[0]; + if (permittedUrls==null) permittedUrls = new String[] { "/favicon.ico", "/health" }; if (securityEnabled && userFormAuthEnabled) { log.debug("afterPropertiesSet: Admin Username: {}", username); @@ -313,8 +313,8 @@ public class WebSecurityConfig implements InitializingBean { && SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().isAuthenticated(); log.trace("WebSecurityConfig: Redirection filters: authenticated={}", isAuthenticated); - if (isAuthenticated && (servletRequest instanceof HttpServletRequest)) { - String uri = ((HttpServletRequest)servletRequest).getRequestURI(); + if (isAuthenticated && (servletRequest instanceof HttpServletRequest request)) { + String uri = request.getRequestURI(); log.trace("WebSecurityConfig: Redirection filters: Request uri={}", uri); if (StringUtils.startsWithAny(uri, loginUrl, loginPage)) { log.debug("WebSecurityConfig: Redirection filter: Redirecting {} to {}...", uri, loginSuccessUrl); @@ -329,8 +329,6 @@ public class WebSecurityConfig implements InitializingBean { httpSecurity //.authorizeHttpRequests( // authorize -> authorize.requestMatchers("/broker/credentials", "/baguette/ref/**").hasAnyRole(ROLE_JWT_TOKEN, ROLE_API_KEY)) - .authorizeHttpRequests( - authorize -> authorize.requestMatchers("/favicon.ico", "/health").permitAll()) .authorizeHttpRequests( authorize -> authorize.requestMatchers(permittedUrls).permitAll()) .authorizeHttpRequests( diff --git a/ems-core/control-service/src/main/resources/META-INF/spring.factories b/nebulous/ems-core/control-service/src/main/resources/META-INF/spring.factories similarity index 100% rename from ems-core/control-service/src/main/resources/META-INF/spring.factories rename to nebulous/ems-core/control-service/src/main/resources/META-INF/spring.factories diff --git a/ems-core/control-service/src/main/resources/banner-0.txt b/nebulous/ems-core/control-service/src/main/resources/banner-0.txt similarity index 100% rename from ems-core/control-service/src/main/resources/banner-0.txt rename to nebulous/ems-core/control-service/src/main/resources/banner-0.txt diff --git a/ems-core/control-service/src/main/resources/banner-1.txt b/nebulous/ems-core/control-service/src/main/resources/banner-1.txt similarity index 100% rename from ems-core/control-service/src/main/resources/banner-1.txt rename to nebulous/ems-core/control-service/src/main/resources/banner-1.txt diff --git a/ems-core/control-service/src/main/resources/banner.txt b/nebulous/ems-core/control-service/src/main/resources/banner.txt similarity index 100% rename from ems-core/control-service/src/main/resources/banner.txt rename to nebulous/ems-core/control-service/src/main/resources/banner.txt diff --git a/ems-core/control-service/src/main/resources/public/client.bat b/nebulous/ems-core/control-service/src/main/resources/public/client.bat similarity index 100% rename from ems-core/control-service/src/main/resources/public/client.bat rename to nebulous/ems-core/control-service/src/main/resources/public/client.bat diff --git a/ems-core/control-service/src/main/resources/public/client.sh b/nebulous/ems-core/control-service/src/main/resources/public/client.sh similarity index 100% rename from ems-core/control-service/src/main/resources/public/client.sh rename to nebulous/ems-core/control-service/src/main/resources/public/client.sh diff --git a/ems-core/control-service/src/main/resources/public/favicon.ico b/nebulous/ems-core/control-service/src/main/resources/public/favicon.ico similarity index 100% rename from ems-core/control-service/src/main/resources/public/favicon.ico rename to nebulous/ems-core/control-service/src/main/resources/public/favicon.ico diff --git a/ems-core/control-service/src/main/resources/public/index.html b/nebulous/ems-core/control-service/src/main/resources/public/index.html similarity index 100% rename from ems-core/control-service/src/main/resources/public/index.html rename to nebulous/ems-core/control-service/src/main/resources/public/index.html diff --git a/ems-core/control-service/src/main/resources/version.txt b/nebulous/ems-core/control-service/src/main/resources/version.txt similarity index 100% rename from ems-core/control-service/src/main/resources/version.txt rename to nebulous/ems-core/control-service/src/main/resources/version.txt diff --git a/ems-core/pom.xml b/nebulous/ems-core/pom.xml similarity index 93% rename from ems-core/pom.xml rename to nebulous/ems-core/pom.xml index 7aeb73d..4f4a6a1 100644 --- a/ems-core/pom.xml +++ b/nebulous/ems-core/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.4 + 3.2.1 @@ -32,8 +32,8 @@ UTF-8 - 17 - 17 + 21 + 21 2.4 @@ -44,31 +44,33 @@ 2.10.1 - 3.13.0 + 3.14.0 - 1.10.0 + 1.11.0 7.1.0 - 4.2.0 + 5.2.1 - 1.18.26 + 1.18.30 - 5.17.5 + 6.0.1 3.0.5 - - 8.0.0.Final - 2.10.0 + 2.11.0 - 1.76 + 1.77 - 32.1.2-jre + 32.1.3-jre + + 1.10.0 + + 1.2.6 - 2.15.2 - 2.0 + 2.16.0 + 2.2 diff --git a/ems-core/translator/pom.xml b/nebulous/ems-core/translator/pom.xml similarity index 100% rename from ems-core/translator/pom.xml rename to nebulous/ems-core/translator/pom.xml diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Grouping.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Grouping.java similarity index 97% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Grouping.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Grouping.java index cf2646e..d74e8ca 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Grouping.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Grouping.java @@ -9,6 +9,9 @@ package gr.iccs.imu.ems.translate; +import lombok.Getter; + +@Getter public enum Grouping { UNSPECIFIED(-1, false, false), PER_INSTANCE(0, true, false), diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/NoopTranslator.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/NoopTranslator.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/NoopTranslator.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/NoopTranslator.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContext.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContext.java similarity index 88% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContext.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContext.java index 07aeab1..da7ef81 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContext.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContext.java @@ -34,12 +34,26 @@ public class TranslationContext implements Serializable { @Getter private final String modelName; + @Getter + private final String modelFileName; + + @Getter @Setter + private String appId; + @Getter @Setter + private String appName; // Decomposition DAG @Getter @JsonIgnore private transient gr.iccs.imu.ems.translate.dag.DAG DAG; + // Extension translation context + @Getter @Setter @JsonIgnore private transient Object extensionContext; + + // Extension translation context helper methods + public Object $() { return extensionContext; } + public T $(Class c) { return c.cast(extensionContext); } + // Event-to-Action map @Getter private final Map> E2A = new HashMap<>(); @@ -109,13 +123,16 @@ public class TranslationContext implements Serializable { // If-Then-Else Constraints private final Set ifThenConstraints = new LinkedHashSet<>(); - // Load-annotated Metric - protected final Map loadAnnotatedDestinationToMetricContextNameMap = new LinkedHashMap<>(); - protected final Set loadAnnotatedMetricsSet = new LinkedHashSet<>(); + // Busy-Status Metrics + protected final Map busyStatusDestinationToMetricContextNameMap = new LinkedHashMap<>(); + protected final Set busyStatusMetricsSet = new LinkedHashSet<>(); // Top-Level metric names protected final Set topLevelMetricNames = new LinkedHashSet<>(); + // Constants defaults + protected final Map constantsDefaults = new LinkedHashMap<>(); + // Export files @Getter @Setter private List exportFiles = new ArrayList<>(); @@ -140,12 +157,17 @@ public class TranslationContext implements Serializable { // Constructors public TranslationContext(String modelName) { - this(true, modelName); + this(true, modelName, null); } - public TranslationContext(boolean initializeDag, String modelName) { + public TranslationContext(String modelName, String modelFileName) { + this(true, modelName, modelFileName); + } + + public TranslationContext(boolean initializeDag, String modelName, String modelFileName) { // Initialize fields this.modelName = modelName; + this.modelFileName = modelFileName; this.DAG = initializeDag ? new DAG(this::getFullName) : new DAG(); // Element-to-Full-Name staff @@ -190,6 +212,7 @@ public class TranslationContext implements Serializable { this.loadAnnotatedDestinationToMetricContextNameMap.putAll(_TC.loadAnnotatedDestinationToMetricContextNameMap); this.loadAnnotatedMetricsSet.addAll(_TC.loadAnnotatedMetricsSet); this.topLevelMetricNames.addAll(_TC.topLevelMetricNames); + this.constantsDefaults.putAll(_TC.constantsDefaults); this.exportFiles.addAll(_TC.exportFiles); this.fullNamePattern = cloneObject(_TC.fullNamePattern); } @@ -258,23 +281,20 @@ public class TranslationContext implements Serializable { // Copy/Getter methods public Map> getG2T() { - HashMap> newMap = new HashMap<>(); - G2T.forEach((key, value) -> newMap.put(key, new HashSet<>(value))); - return newMap; + return G2T.keySet().stream().map(Grouping::valueOf).sorted().collect(Collectors.toMap( + Enum::name, e->G2T.get(e.name()), (oldval, newval) -> oldval, LinkedHashMap::new)); } public Map>> getG2R() { - Map>> newGroupingsMap = new HashMap<>(); // groupings - G2R.forEach((key, value) -> { - Map> newTopicsMap = new HashMap<>(); // topics per grouping - newGroupingsMap.put(key, newTopicsMap); - value.forEach((key1, value1) -> { - Set newRuleSet = new HashSet<>(); // rules per topic per grouping - newTopicsMap.put(key1, newRuleSet); - newRuleSet.addAll(value1); - }); - }); - return newGroupingsMap; + return G2R.keySet().stream().map(Grouping::valueOf).sorted().collect(Collectors.toMap( // groupings + Enum::name, grouping -> { + Map> topicsMap = G2R.get(grouping.name()); // topics per grouping + return topicsMap.keySet().stream().sorted().collect(Collectors.toMap( + t->t, t -> new HashSet<>(topicsMap.get(t)), // rules per topic per grouping + (oldval, newval) -> oldval, LinkedHashMap::new + )); + }, (oldval, newval) -> oldval, LinkedHashMap::new + )); } public Set getMetricConstraints() { @@ -285,6 +305,10 @@ public class TranslationContext implements Serializable { return logicalConstraints!=null ? new HashSet<>(logicalConstraints) : new HashSet<>(); } + public Set getIfThenConstraints() { + return ifThenConstraints!=null ? new HashSet<>(ifThenConstraints) : new HashSet<>(); + } + public HashSet getCompositeMetricVariables() { return CMVar_1!=null ? new HashSet<>(CMVar_1) : new HashSet<>(); } @@ -326,7 +350,7 @@ public class TranslationContext implements Serializable { valueSet = new HashSet<>(); map.put(key, valueSet); } - if (value instanceof List) valueSet.addAll((List) value); + if (value instanceof List list) valueSet.addAll(list); else valueSet.add(value); } @@ -423,6 +447,10 @@ public class TranslationContext implements Serializable { MvvCP.put(matchingVarName, varName); } + public boolean containsFunction(String name) { + return FUNC.stream().anyMatch(fd -> fd.getName().equals(name)); + } + public void addFunction(Function f) { FunctionDefinition fdef = new FunctionDefinition().setName(f.getName()).setExpression(f.getExpression()).setArguments(f.getArguments()); FUNC.add(fdef); @@ -460,7 +488,7 @@ public class TranslationContext implements Serializable { ); } - public void addLogicalConstraint(LogicalConstraint logicalConstraint, List nodeList) { + public void addLogicalConstraint(LogicalConstraint logicalConstraint) { String name = logicalConstraint.getName(); // Check there is a logical operator @@ -471,7 +499,7 @@ public class TranslationContext implements Serializable { // Check there are child constraints List childConstraintNames = logicalConstraint.getConstraints() .stream().map(NamedElement::getName).toList(); - if (childConstraintNames.size()==0) + if (childConstraintNames.isEmpty()) throw new IllegalArgumentException("Logical Constraint '"+name+"' has no child constraints"); // Add logical constraint information @@ -655,35 +683,35 @@ public class TranslationContext implements Serializable { } // ==================================================================================================================================================== - // Load-Metrics-related helper methods + // Busy-Status metrics-related helper methods - public void addLoadAnnotatedDestinationNameToMetricContextName(@NonNull String metricContextName, @NonNull String destinationName) { - loadAnnotatedDestinationToMetricContextNameMap.put(destinationName, metricContextName); + public void addBusyStatusDestinationNameToMetricContextName(@NonNull String metricContextName, @NonNull String destinationName) { + busyStatusDestinationToMetricContextNameMap.put(destinationName, metricContextName); } - public void addLoadAnnotatedDestinationNameToMetricContextName(@NonNull Map map) { - loadAnnotatedDestinationToMetricContextNameMap.putAll(map); + public void addBusyStatusDestinationNameToMetricContextName(@NonNull Map map) { + busyStatusDestinationToMetricContextNameMap.putAll(map); } - public Map getLoadAnnotatedDestinationNameToMetricContextNameMap() { - return loadAnnotatedDestinationToMetricContextNameMap!=null - ? new HashMap<>(loadAnnotatedDestinationToMetricContextNameMap) : new HashMap<>(); + public Map getBusyStatusDestinationNameToMetricContextNameMap() { + return busyStatusDestinationToMetricContextNameMap!=null + ? new HashMap<>(busyStatusDestinationToMetricContextNameMap) : new HashMap<>(); } - public String getLoadAnnotatedDestinationMetricContextName(@NonNull String key) { - return getLoadAnnotatedDestinationNameToMetricContextNameMap().get(key); + public String getBusyStatusDestinationMetricContextName(@NonNull String key) { + return getBusyStatusDestinationNameToMetricContextNameMap().get(key); } - public void addLoadAnnotatedMetric(@NonNull String metricName) { - loadAnnotatedMetricsSet.add(metricName); + public void addBusyStatusMetric(@NonNull String metricName) { + busyStatusMetricsSet.add(metricName); } - public void addLoadAnnotatedMetrics(@NonNull Set metricNames) { - loadAnnotatedMetricsSet.addAll(metricNames); + public void addBusyStatusMetrics(@NonNull Set metricNames) { + busyStatusMetricsSet.addAll(metricNames); } - public Set getLoadAnnotatedMetricsSet() { - return loadAnnotatedMetricsSet!=null ? new HashSet<>(loadAnnotatedMetricsSet) : new HashSet<>(); + public Set getBusyStatusMetricsSet() { + return busyStatusMetricsSet!=null ? new HashSet<>(busyStatusMetricsSet) : new HashSet<>(); } // ==================================================================================================================================================== @@ -719,6 +747,21 @@ public class TranslationContext implements Serializable { return topLevelMetricNames!=null ? new HashSet<>(topLevelMetricNames) : Collections.emptySet(); } + // ==================================================================================================================================================== + // Constants helper methods + + public void addConstantDefault(String constantName, double defaultValue) { + this.constantsDefaults.put(constantName, defaultValue); + } + + public void addConstantDefaults(Map constantsDefaults) { + this.constantsDefaults.putAll(constantsDefaults); + } + + public Map getConstantDefaults() { + return new LinkedHashMap<>(this.constantsDefaults); + } + // ==================================================================================================================================================== // Additional results helper methods diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinter.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinter.java similarity index 79% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinter.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinter.java index 59297e1..2428015 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinter.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinter.java @@ -9,6 +9,7 @@ package gr.iccs.imu.ems.translate; +import gr.iccs.imu.ems.translate.dag.DAGExporter; import gr.iccs.imu.ems.translate.model.NamedElement; import gr.iccs.imu.ems.util.FunctionDefinition; import lombok.RequiredArgsConstructor; @@ -24,7 +25,8 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class TranslationContextPrinter { private final TranslationContextPrinterProperties properties; - + private final DAGExporter dagExporter; + public void printResults(TranslationContext _TC, String exportName) { if (! properties.isPrintResults()) { log.debug("TranslationContextPrinter.printResults(): Translation results printing is disabled"); @@ -44,7 +46,7 @@ public class TranslationContextPrinter { log.info("*********************************************************"); try { if (_TC.getDAG().getRootNode()!=null) { - dot = _TC.getDAG().exportToDot(); + dot = dagExporter.exportToDot(_TC.getDAG()); log.info("Decomposition Graph in DOT format:\n{}", dot); } else { log.warn("Decomposition Graph is empty."); @@ -65,15 +67,15 @@ public class TranslationContextPrinter { int imageWidth = properties.getDag().getExportImageWidth(); // Get base name and path of export files - if (exportPath == null) exportPath = ""; + if (StringUtils.isBlank(exportPath)) exportPath = ""; exportName = StringUtils.stripToEmpty(exportName); - if (exportName.isEmpty()) exportName = "noname"; - String baseFileName = String.format("%s/%s-%d", exportPath, exportName, System.currentTimeMillis()); + if (exportName.isEmpty()) exportName = "export"; + String baseFileName = "%s/%s-%d".formatted(exportPath, exportName, System.currentTimeMillis()); List exportFiles; if (dot!=null) { - exportFiles = _TC.getDAG().exportDAG(dot, baseFileName, exportFormats, imageWidth); + exportFiles = dagExporter.exportDAG(dot, baseFileName, exportFormats, imageWidth); } else { - exportFiles = _TC.getDAG().exportDAG(baseFileName, exportFormats, imageWidth); + exportFiles = dagExporter.exportDAG(_TC.getDAG(), baseFileName, exportFormats, imageWidth); } _TC.setExportFiles(exportFiles); //log.info("Decomposition Graph export to file(s): ok"); @@ -96,9 +98,22 @@ public class TranslationContextPrinter { log.info("*********************************************************"); log.info("Grouping-to-EPL Rules map:\n{}", prettifyG2R(_TC.getG2R(), "")); log.info("*********************************************************"); - log.info("Grouping-to-Topics map:\n{}", _TC.getG2T()); + log.info("Grouping-to-Topics map:\n{}", _TC.getG2T().entrySet().stream() + .sorted(Comparator.comparingInt(o -> Grouping.valueOf(o.getKey()).ordinal())) + .map(e -> e.getKey()+": "+e.getValue().stream() + .collect(Collectors.joining("\n - ", "\n - ", "")) ) + .collect(Collectors.joining("\n ", " ", ""))); log.info("*********************************************************"); - log.info("Topics-Connections map:\n{}", _TC.getTopicConnections()); + log.info("Topics-Connections map:\n{}", _TC.getTopicConnections().entrySet().stream() + .sorted(Comparator.comparingInt(o -> Grouping.valueOf(o.getKey()).ordinal())) + .map(e -> e.getKey()+": "+ e.getValue().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .map(ee -> ee.getKey()+": "+ee.getValue().stream() + .sorted(Comparator.comparingInt(o -> Grouping.valueOf(o).ordinal())) + .toList()) + .collect(Collectors.joining("\n ", "\n ", "")) + ) + .collect(Collectors.joining("\n ", " ", ""))); log.info("*********************************************************"); log.info("MVV set:\n{}", _TC.getMVV()); log.info("*********************************************************"); @@ -112,10 +127,10 @@ public class TranslationContextPrinter { log.info("*********************************************************"); log.info("Metric Constraints:\n{}", _TC.getMetricConstraints()); log.info("*********************************************************"); - log.info("Load-Annotated Destination-to-Metric Context names map:\n{}", - _TC.getLoadAnnotatedDestinationNameToMetricContextNameMap()); + log.info("Busy-Status Destination-to-Metric Context names map:\n{}", + _TC.getBusyStatusDestinationNameToMetricContextNameMap()); log.info("*********************************************************"); - log.info("Load-Annotated Metrics:\n{}", _TC.getLoadAnnotatedMetricsSet()); + log.info("Busy-Status Metrics:\n{}", _TC.getBusyStatusMetricsSet()); log.info("*********************************************************"); log.info("Top-Level Metric names:\n{}", _TC.getTopLevelMetricNames()); log.info("*********************************************************"); @@ -165,14 +180,14 @@ public class TranslationContextPrinter { if (key==null) { newMap.put( key+"::"+key, list ); } else - if (key instanceof NamedElement) { - newMap.put( key.getClass().getSimpleName()+"::"+((NamedElement)key).getName(), list ); + if (key instanceof NamedElement element) { + newMap.put( key.getClass().getSimpleName()+"::"+element.getName(), list ); } else { newMap.put( key.getClass().getSimpleName()+"::"+key, list ); } for (Object val : values) { - if (val instanceof NamedElement) { - list.add( val.getClass().getSimpleName()+"::"+((NamedElement)val).getName() ); + if (val instanceof NamedElement element) { + list.add( val.getClass().getSimpleName()+"::"+element.getName() ); } else { list.add( val.getClass().getSimpleName()+"::"+val ); } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinterProperties.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinterProperties.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinterProperties.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslationContextPrinterProperties.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Translator.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Translator.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Translator.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/Translator.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslatorApplication.java_OFF b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslatorApplication.java_OFF similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslatorApplication.java_OFF rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/TranslatorApplication.java_OFF diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAG.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAG.java similarity index 74% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAG.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAG.java index 51dde05..92cf5d4 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAG.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAG.java @@ -11,22 +11,9 @@ package gr.iccs.imu.ems.translate.dag; import com.fasterxml.jackson.annotation.JsonIgnore; import gr.iccs.imu.ems.translate.model.NamedElement; -import guru.nidi.graphviz.engine.Format; -import guru.nidi.graphviz.engine.Graphviz; -import guru.nidi.graphviz.engine.GraphvizV8Engine; -import guru.nidi.graphviz.model.MutableGraph; -import guru.nidi.graphviz.parse.Parser; -import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.jgrapht.graph.DirectedAcyclicGraph; -import org.jgrapht.nio.Attribute; -import org.jgrapht.nio.AttributeType; -import org.jgrapht.nio.DefaultAttribute; -import org.jgrapht.nio.dot.DOTExporter; -import java.io.File; -import java.io.StringWriter; -import java.io.Writer; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -36,7 +23,7 @@ public class DAG { // Graph-related fields @JsonIgnore private transient Function fullNameProvider = NamedElement::getName; - private DirectedAcyclicGraph _graph; + DirectedAcyclicGraph _graph; @JsonIgnore private transient DAGNode _root; @JsonIgnore @@ -283,8 +270,8 @@ public class DAG { else log.debug("DAG.addEdge(): Edge is already in DAG: {} --> {}", elemFrom, elemTo); return edge; } else { - throw new RuntimeException(String.format("Adding edge FAILED: elem-from=%s -> elem-to=%s. Node not found in DAG: node-from=%s --> node-to=%s", - elemFrom, elemTo, (nodeFrom != null ? nodeFrom.getName() : null), (nodeTo != null ? nodeTo.getName() : null))); + throw new RuntimeException("Adding edge FAILED: elem-from=%s -> elem-to=%s. Node not found in DAG: node-from=%s --> node-to=%s" + .formatted(elemFrom, elemTo, (nodeFrom != null ? nodeFrom.getName() : null), (nodeTo != null ? nodeTo.getName() : null))); } } @@ -356,104 +343,6 @@ public class DAG { _graph.addEdge(src, trg); } - // ==================================================================================================================================================== - // Export methods - - public String exportToDot() { - if (_graph==null) { - log.warn("DAG.exportToDot(): Cannot export: DAG has not been initialized"); - return null; - } - - DOTExporter exporter = new DOTExporter<>(node -> "NODE_" + node.getId()); - exporter.setVertexAttributeProvider(node -> { - LinkedHashMap vertexAttributes = new LinkedHashMap<>(); - String label; - if (node.getName() != null) { - if (node.getGrouping() != null) { - label = String.format("%s\n[%s]", node.getName(), node.getGrouping()); - } else { - label = node.getName(); - } - } else { - label = ""; - } - // See: https://graphviz.org/doc/info/attrs.html - vertexAttributes.put("label", new DefaultAttribute<>(label, AttributeType.STRING)); - /* - vertexAttributes.put("color", new DefaultAttribute<>("red", AttributeType.STRING)); - vertexAttributes.put("fontcolor", new DefaultAttribute<>("yellow", AttributeType.STRING)); - vertexAttributes.put("fillcolor", new DefaultAttribute<>("cyan:green;0.3", AttributeType.STRING)); - vertexAttributes.put("style", new DefaultAttribute<>("radial", AttributeType.STRING)); - vertexAttributes.put("gradientangle", new DefaultAttribute<>(60, AttributeType.INT)); - */ - return vertexAttributes; - }); - Writer writer = new StringWriter(); - exporter.exportGraph(_graph, writer); - return writer.toString(); - } - - public List exportDAG(String baseFileName, String[] exportFormats, int imageWidth) { - try { - if (!checkExportConfiguration(baseFileName, exportFormats, imageWidth)) return null; - - // Export DAG in DOT format (can be viewd with GraphViz tool) - String dot = exportToDot(); - log.debug("DAG.exportDAG(): Results of exportToDot(): Graph in DOT format:\n{}", dot); - if (dot==null) { - log.warn("DAG.exportDAG(): Cannot export: DAG has not been initialized"); - return null; - } - - // Export DOT into specified formats and save to file(s) - return exportDAG(dot, baseFileName, exportFormats, imageWidth); - - } catch (Exception ex) { - log.error("DAG.exportDAG(): Graph export FAILED: ", ex); - return null; - } - } - - public List exportDAG(@NonNull String dot, String baseFileName, String[] exportFormats, int imageWidth) { - try { - if (!checkExportConfiguration(baseFileName, exportFormats, imageWidth)) return null; - - // Configure Graphviz rendering engine to V8. It's faster - // See also: https://github.com/nidi3/graphviz-java - Graphviz.useEngine(new GraphvizV8Engine()); - - // Export DOT into specified formats and save to file(s) - List exportFilesList = new LinkedList<>(); - MutableGraph mg = new Parser().read(dot); - for (String f : exportFormats) { - Format fmt = Format.valueOf(f.toUpperCase()); - String exportFile = baseFileName + "." + f; - Graphviz.fromGraph(mg).width(imageWidth).render(fmt).toFile(new File(exportFile)); - exportFilesList.add(exportFile); - log.info("DAG.exportDAG(): Graph exported in {} format: {}", fmt, exportFile); - } - return exportFilesList; - - } catch (Exception ex) { - log.error("DAG.exportDAG(): Graph export FAILED: ", ex); - return null; - } - } - - protected boolean checkExportConfiguration(String baseFileName, String[] exportFormats, int imageWidth) { - // check export configuration - if (exportFormats == null || exportFormats.length == 0) { - log.warn("DAG.checkExportConfiguration(): No export formats specified for Graph export: {}", Arrays.toString(exportFormats)); - return false; - } - if (imageWidth < 1) { - log.warn("DAG.checkExportConfiguration(): Invalid image width for Graph export: {}", imageWidth); - return false; - } - return true; - } - public String toString() { return _graph!=null ? _graph.toString() : null; } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGEdge.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGEdge.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGEdge.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGEdge.java diff --git a/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGExporter.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGExporter.java new file mode 100644 index 0000000..9224200 --- /dev/null +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGExporter.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package gr.iccs.imu.ems.translate.dag; + +import guru.nidi.graphviz.engine.Format; +import guru.nidi.graphviz.engine.Graphviz; +import guru.nidi.graphviz.engine.GraphvizV8Engine; +import guru.nidi.graphviz.model.MutableGraph; +import guru.nidi.graphviz.parse.Parser; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.AttributeType; +import org.jgrapht.nio.DefaultAttribute; +import org.jgrapht.nio.dot.DOTExporter; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; + +@Slf4j +@Service +public class DAGExporter { + public String exportToDot(DAG dag) { + if (dag._graph==null) { + log.warn("DAG.exportToDot(): Cannot export: DAG has not been initialized"); + return null; + } + + // Create a DOT exporter + DOTExporter exporter = new DOTExporter<>(node -> "NODE_" + node.getId()); + + // Format the graph + /*exporter.setGraphAttributeProvider(() -> { + LinkedHashMap graphAttributes = new LinkedHashMap<>(); + // See: https://graphviz.org/docs/layouts/ + graphAttributes.put("layout", new DefaultAttribute<>("circo", AttributeType.STRING)); + graphAttributes.put("beautify", new DefaultAttribute<>("true", AttributeType.BOOLEAN)); + return graphAttributes; + });*/ + + // Format vertices (nodes) + // See (colors): https://www.pastelcolorpalettes.com/7-color-pastels-rainbow + List ll = Arrays.asList("#F6CA94", "#FAFABE", "#C1EBC0", "#C7CAFF", "#CDABEB", "#F6C2F3", "#F09EA7"); + //Collections.reverse(ll); + String[] colorsArr = ll.toArray(new String[0]); + exporter.setVertexAttributeProvider(node -> { + LinkedHashMap vertexAttributes = new LinkedHashMap<>(); + + // Prepare and format labels + // See: https://graphviz.org/doc/info/shapes.html#html + String label; + String col; + boolean isRoot = false, isSensor = false; + boolean isBusyStatus = false, isMetricVar = false; + if (node.getName() != null) { + if (node.getGrouping() != null) { + //label = String.format("%s\n[%s]", node.getName(), node.getGrouping()); + String[] namePart = node.getName().split("\\.",2); + String name = (namePart.length>1) + ? ""+namePart[0].trim()+" .."+namePart[1].trim() : ""+namePart[0].trim()+""; + String type = node.getElement()!=null ? node.getElement().getClass().getSimpleName() : "-"; + String topic = StringUtils.defaultIfBlank(node.getTopicName(), ""); + label = String.format(""" + %s +
+ « %s » +
+ %s +
+ [%s] + """, + name, type, topic, node.getGrouping()); + col = colorsArr[(node.getGrouping().getOrder() % (colorsArr.length-1))]; + + isSensor = node.getElement()!=null && + StringUtils.containsIgnoreCase(node.getElement().getClass().getSimpleName(), "Sensor"); + isBusyStatus = node.getElement()!=null && + "BusyStatusMetricVariable".equalsIgnoreCase(node.getElement().getClass().getSimpleName()); + isMetricVar = node.getElement()!=null && + "MetricVariable".equalsIgnoreCase(node.getElement().getClass().getSimpleName()); + } else { + label = node.getName(); + col = "#ffffff"; + } + } else { + label = StringEscapeUtils.escapeHtml4(""); + label = ""+label+""; + col = colorsArr[colorsArr.length-1]; + isRoot = true; + } + // See: https://graphviz.org/doc/info/attrs.html + vertexAttributes.put("label", new DefaultAttribute<>(label, AttributeType.HTML)); + + // See: https://graphviz.org/doc/info/shapes.html#polygon + vertexAttributes.put("shape", new DefaultAttribute<>( + isRoot || isSensor ? "oval" : "box", AttributeType.STRING)); + + vertexAttributes.put("fillcolor", new DefaultAttribute<>(col+":white;0.3", AttributeType.STRING)); + if (isSensor) + vertexAttributes.put("fillcolor", new DefaultAttribute<>("white", AttributeType.STRING)); + if (isBusyStatus) + vertexAttributes.put("fillcolor", new DefaultAttribute<>("yellow:white;0.3", AttributeType.STRING)); + if (isMetricVar) + vertexAttributes.put("fillcolor", new DefaultAttribute<>("orange:white;0.3", AttributeType.STRING)); + vertexAttributes.put("style", new DefaultAttribute<>("radial, rounded", AttributeType.STRING)); + //vertexAttributes.put("style", new DefaultAttribute<>("filled", AttributeType.STRING)); + vertexAttributes.put("gradientangle", new DefaultAttribute<>(60, AttributeType.INT)); + + /*if (isSensor) { + if (((Sensor) node.getElement()).getAdditionalProperties()!=null) { + String sensorType = ((Sensor) node.getElement()).getAdditionalProperties() + .getOrDefault("type", "").trim().toLowerCase(); + String image = switch (sensorType) { + case "netdata" -> "netdata-48x48.png"; + default -> null; + }; + if (StringUtils.isNotBlank(image)) { + vertexAttributes.put("image", new DefaultAttribute<>(image, AttributeType.STRING)); + vertexAttributes.put("imagepos", new DefaultAttribute<>("ml", AttributeType.STRING)); + } + } + }*/ + return vertexAttributes; + }); + + // Format edges + exporter.setEdgeAttributeProvider(edge -> { + LinkedHashMap edgeAttributes = new LinkedHashMap<>(); +// edgeAttributes.put("dir", new DefaultAttribute<>("back", AttributeType.STRING)); + edgeAttributes.put("arrowtail", new DefaultAttribute<>("vee", AttributeType.STRING)); + return edgeAttributes; + }); + + // Export graph to DOT string + Writer writer = new StringWriter(); + exporter.exportGraph(dag._graph, writer); + return writer.toString(); + } + + public List exportDAG(DAG dag, String baseFileName, String[] exportFormats, int imageWidth) { + try { + if (!checkExportConfiguration(baseFileName, exportFormats, imageWidth)) return null; + + // Export DAG in DOT format (can be viewed with GraphViz tool) + String dot = exportToDot(dag); + log.debug("DAG.exportDAG(): Results of exportToDot(): Graph in DOT format:\n{}", dot); + if (dot==null) { + log.warn("DAG.exportDAG(): Cannot export: DAG has not been initialized"); + return null; + } + + // Export DOT into specified formats and save to file(s) + return exportDAG(dot, baseFileName, exportFormats, imageWidth); + + } catch (Exception ex) { + log.error("DAG.exportDAG(): Graph export FAILED: ", ex); + return null; + } + } + + public List exportDAG(@NonNull String dot, String baseFileName, String[] exportFormats, int imageWidth) { + try { + if (!checkExportConfiguration(baseFileName, exportFormats, imageWidth)) return null; + + // Configure Graphviz rendering engine to V8. It's faster + // See also: https://github.com/nidi3/graphviz-java + Graphviz.useEngine(new GraphvizV8Engine()); + + // Export DOT into specified formats and save to file(s) + List exportFilesList = new LinkedList<>(); + MutableGraph mg = new Parser().read(dot); + for (String f : exportFormats) { + Format fmt = Format.valueOf(f.toUpperCase()); + String exportFile = baseFileName + "." + f; + Graphviz.fromGraph(mg).width(imageWidth).render(fmt).toFile(new File(exportFile)); + exportFilesList.add(exportFile); + log.info("DAG.exportDAG(): Graph exported in {} format: {}", fmt, exportFile); + } + return exportFilesList; + + } catch (Exception ex) { + log.error("DAG.exportDAG(): Graph export FAILED: ", ex); + return null; + } + } + + protected boolean checkExportConfiguration(String baseFileName, String[] exportFormats, int imageWidth) { + // check export configuration + if (exportFormats == null || exportFormats.length == 0) { + log.warn("DAG.checkExportConfiguration(): No export formats specified for Graph export: {}", Arrays.toString(exportFormats)); + return false; + } + if (imageWidth < 1) { + log.warn("DAG.checkExportConfiguration(): Invalid image width for Graph export: {}", imageWidth); + return false; + } + return true; + } +} diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGNode.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGNode.java similarity index 87% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGNode.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGNode.java index 336a308..1412c4c 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGNode.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/dag/DAGNode.java @@ -16,6 +16,8 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; @@ -29,6 +31,8 @@ public class DAGNode implements Serializable { private final NamedElement element; private final String elementName; private Grouping grouping; + private String topicName; + private final Map properties = new LinkedHashMap<>(); DAGNode() { id = counter.getAndIncrement(); @@ -49,6 +53,11 @@ public class DAGNode implements Serializable { return this; } + public DAGNode setTopicName(String s) { + topicName = s; + return this; + } + public int hashCode() { return toString().hashCode(); } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractInterfaceRootObject.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractInterfaceRootObject.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractInterfaceRootObject.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractInterfaceRootObject.java index 32a3e89..0f2fd39 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractInterfaceRootObject.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractInterfaceRootObject.java @@ -11,6 +11,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.io.Serializable; @@ -19,6 +20,7 @@ import java.util.Map; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public abstract class AbstractInterfaceRootObject extends AbstractRootObject { protected Map additionalProperties; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractRootObject.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractRootObject.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractRootObject.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/AbstractRootObject.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Action.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Action.java similarity index 92% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Action.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Action.java index 4e9b558..7e08923 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Action.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Action.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Action extends Feature { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Annotation.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Annotation.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Annotation.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Annotation.java index 78e7111..33b6f5c 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Annotation.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Annotation.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Annotation extends AbstractRootObject { protected String id; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Attribute.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Attribute.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Attribute.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Attribute.java index 1e585ff..ce12395 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Attribute.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Attribute.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Attribute extends NamedElement { private Object value; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryEventPattern.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryEventPattern.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryEventPattern.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryEventPattern.java index 3c2a5e6..e8d6e85 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryEventPattern.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryEventPattern.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class BinaryEventPattern extends EventPattern { private Event leftEvent; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryPatternOperatorType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryPatternOperatorType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryPatternOperatorType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BinaryPatternOperatorType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BooleanValue.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BooleanValue.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BooleanValue.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BooleanValue.java index 7e34bd9..5ac09fa 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BooleanValue.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BooleanValue.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class BooleanValue extends Value { private boolean value; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LoadMetricVariable.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BusyStatusMetricVariable.java similarity index 79% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LoadMetricVariable.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BusyStatusMetricVariable.java index f6eb633..5ab1313 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LoadMetricVariable.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/BusyStatusMetricVariable.java @@ -11,14 +11,16 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) -public class LoadMetricVariable extends MetricVariable { - public LoadMetricVariable(String name, MetricContext context) { +public class BusyStatusMetricVariable extends MetricVariable { + public BusyStatusMetricVariable(String name, MetricContext context) { setName(name); setMetricContext(context); } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ComparisonOperatorType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ComparisonOperatorType.java similarity index 75% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ComparisonOperatorType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ComparisonOperatorType.java index 6d1696e..67fe025 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ComparisonOperatorType.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ComparisonOperatorType.java @@ -24,4 +24,11 @@ public enum ComparisonOperatorType { private final String name; private final String operator; + + public static ComparisonOperatorType byOperator(String s) { + for (ComparisonOperatorType e : values()) + if (e.operator.equals(s)) + return e; + throw new IllegalArgumentException("No "+EQUAL.getClass().getName()+" with operator: "+s); + } } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Component.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Component.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Component.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Component.java index 0be04c8..d9f3efe 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Component.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Component.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Component extends Feature { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeConstraint.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeConstraint.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeConstraint.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeConstraint.java index bd6c393..9c10ea4 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeConstraint.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeConstraint.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class CompositeConstraint extends Constraint { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetric.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetric.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetric.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetric.java index 09af481..7c60667 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetric.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetric.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class CompositeMetric extends Metric { private String formula; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetricContext.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetricContext.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetricContext.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetricContext.java index 2419b25..8d52f03 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetricContext.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CompositeMetricContext.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class CompositeMetricContext extends MetricContext { private GroupingType groupingType; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Constraint.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Constraint.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Constraint.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Constraint.java index 7639a7e..166b491 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Constraint.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Constraint.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Constraint extends NamedElement { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CriterionType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CriterionType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CriterionType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/CriterionType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Data.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Data.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Data.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Data.java index c1fcf9b..3bad8b7 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Data.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Data.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder() @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Data extends Feature { private DataSource dataSource; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DataSource.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DataSource.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DataSource.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DataSource.java index 9f0cbc9..5bc8c82 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DataSource.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DataSource.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class DataSource extends Feature { private boolean external; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DoubleValue.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DoubleValue.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DoubleValue.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DoubleValue.java index f63e2bb..27f252f 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DoubleValue.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/DoubleValue.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class DoubleValue extends NumericValue { private double value; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Event.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Event.java similarity index 92% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Event.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Event.java index 2eeeaaf..4d751a0 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Event.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Event.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Event extends Feature { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/EventPattern.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/EventPattern.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/EventPattern.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/EventPattern.java index 4e74576..53bc4d7 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/EventPattern.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/EventPattern.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class EventPattern extends Event { private Timer timer; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Feature.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Feature.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Feature.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Feature.java index 98582f4..1f123f8 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Feature.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Feature.java @@ -11,6 +11,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.List; @@ -18,6 +19,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Feature extends NamedElement { protected List attributes; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/FloatValue.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/FloatValue.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/FloatValue.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/FloatValue.java index 5686da2..a450083 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/FloatValue.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/FloatValue.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class FloatValue extends NumericValue { private float value; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Function.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Function.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Function.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Function.java index d57ba2f..97e2bb4 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Function.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Function.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Function extends Feature { private String expression; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/GroupingType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/GroupingType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/GroupingType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/GroupingType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IfThenConstraint.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IfThenConstraint.java similarity index 95% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IfThenConstraint.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IfThenConstraint.java index 7f7cd55..2c85a7e 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IfThenConstraint.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IfThenConstraint.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class IfThenConstraint extends CompositeConstraint { private Constraint ifConstraint; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IntValue.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IntValue.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IntValue.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IntValue.java index f534049..60d868f 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IntValue.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/IntValue.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class IntValue extends NumericValue { private int value; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Interval.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Interval.java similarity index 97% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Interval.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Interval.java index 0680763..cb88ddc 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Interval.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Interval.java @@ -17,6 +17,7 @@ import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) // See: eu.melodic.models.interfaces.Interval public class Interval extends AbstractInterfaceRootObject { diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalConstraint.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalConstraint.java similarity index 89% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalConstraint.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalConstraint.java index ff41a76..cfbf4e6 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalConstraint.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalConstraint.java @@ -9,10 +9,7 @@ package gr.iccs.imu.ems.translate.model; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.NonNull; +import lombok.*; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -21,6 +18,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class LogicalConstraint extends CompositeConstraint { private LogicalOperatorType logicalOperator; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalOperatorType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalOperatorType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalOperatorType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/LogicalOperatorType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MeasurableAttribute.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MeasurableAttribute.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MeasurableAttribute.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MeasurableAttribute.java index 034888c..b7b2256 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MeasurableAttribute.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MeasurableAttribute.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class MeasurableAttribute extends Attribute { @Builder.Default diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Metric.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Metric.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Metric.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Metric.java index 1dfe13a..3c59654 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Metric.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Metric.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Metric extends Feature { protected MetricTemplate metricTemplate; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricConstraint.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricConstraint.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricConstraint.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricConstraint.java index cd45f32..1603e40 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricConstraint.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricConstraint.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class MetricConstraint extends UnaryConstraint { private MetricContext metricContext; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricContext.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricContext.java similarity index 95% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricContext.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricContext.java index 3198c75..dbc3fba 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricContext.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricContext.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class MetricContext extends Feature { private Metric metric; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricTemplate.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricTemplate.java similarity index 62% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricTemplate.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricTemplate.java index a7d9487..817e13d 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricTemplate.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricTemplate.java @@ -9,17 +9,32 @@ package gr.iccs.imu.ems.translate.model; +import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; +import java.util.List; + @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class MetricTemplate extends Feature { + public final static short FORWARD_DIRECTION = 1; + public final static short BACKWARD_DIRECTION = -1; + private ValueType valueType; - private short valueDirection; + @Builder.Default + private short valueDirection = FORWARD_DIRECTION; private String unit; private MeasurableAttribute attribute; + + @Builder.Default + private double lowerBound = Double.NEGATIVE_INFINITY; + @Builder.Default + private double upperBound = Double.POSITIVE_INFINITY; + private List allowedValues; } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariable.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariable.java similarity index 95% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariable.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariable.java index 974df1c..ee836cc 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariable.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariable.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class MetricVariable extends Metric { private boolean currentConfiguration; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariableConstraint.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariableConstraint.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariableConstraint.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariableConstraint.java index 2e882ce..22bf233 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariableConstraint.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/MetricVariableConstraint.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class MetricVariableConstraint extends UnaryConstraint { private MetricVariable metricVariable; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Monitor.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Monitor.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Monitor.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Monitor.java index 74655be..a0dda10 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Monitor.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Monitor.java @@ -11,6 +11,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.List; @@ -19,6 +20,7 @@ import java.util.Map; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) // See: eu.melodic.models.interfaces.Monitor public class Monitor extends AbstractInterfaceRootObject { diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NamedElement.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NamedElement.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NamedElement.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NamedElement.java index 03d8da2..f41cbb1 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NamedElement.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NamedElement.java @@ -11,6 +11,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.List; @@ -18,6 +19,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class NamedElement extends AbstractRootObject { protected String name; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NonFunctionalEvent.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NonFunctionalEvent.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NonFunctionalEvent.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NonFunctionalEvent.java index 16d6e19..5512903 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NonFunctionalEvent.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NonFunctionalEvent.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class NonFunctionalEvent extends SingleEvent { private MetricConstraint metricConstraint; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NumericValue.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NumericValue.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NumericValue.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NumericValue.java index 03ba42a..3e5fa54 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NumericValue.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/NumericValue.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class NumericValue extends Value { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ObjectContext.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ObjectContext.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ObjectContext.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ObjectContext.java index b4614d3..0cd9b8d 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ObjectContext.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ObjectContext.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class ObjectContext extends Feature { private Component component; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/OptimisationRequirement.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/OptimisationRequirement.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/OptimisationRequirement.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/OptimisationRequirement.java index 67f98dd..cfb38e2 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/OptimisationRequirement.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/OptimisationRequirement.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class OptimisationRequirement extends Requirement { // SoftRequirement private double priority; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PullSensor.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PullSensor.java similarity index 83% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PullSensor.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PullSensor.java index bc06dbb..90b94f4 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PullSensor.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PullSensor.java @@ -9,22 +9,18 @@ package gr.iccs.imu.ems.translate.model; -import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; -import java.util.HashMap; -import java.util.Map; - @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) // Based on: eu.melodic.models.interfaces.PullSensor public class PullSensor extends Sensor { private String className; - @Builder.Default - private Map configuration = new HashMap<>(); private Interval interval; } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PushSensor.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PushSensor.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PushSensor.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PushSensor.java index b0de16d..f2e7172 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PushSensor.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/PushSensor.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) // Based on: eu.melodic.models.interfaces.PushSensor public class PushSensor extends Sensor { diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetric.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetric.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetric.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetric.java index d8d5fe2..69486f7 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetric.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetric.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class RawMetric extends Metric { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetricContext.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetricContext.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetricContext.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetricContext.java index 8edb825..7837178 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetricContext.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/RawMetricContext.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class RawMetricContext extends MetricContext { private Sensor sensor; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Requirement.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Requirement.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Requirement.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Requirement.java index 6cb3588..ac41906 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Requirement.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Requirement.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Requirement extends Feature { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalabilityRule.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalabilityRule.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalabilityRule.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalabilityRule.java index 9ba36de..bde8e48 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalabilityRule.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalabilityRule.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class ScalabilityRule extends Feature { private Event event; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalingAction.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalingAction.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalingAction.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalingAction.java index cc8df30..61e4d2e 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalingAction.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ScalingAction.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class ScalingAction extends Action { private Component component; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Schedule.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Schedule.java similarity index 79% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Schedule.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Schedule.java index d74f3cf..24169b9 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Schedule.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Schedule.java @@ -11,6 +11,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.Date; @@ -19,13 +20,19 @@ import java.util.concurrent.TimeUnit; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Schedule extends Feature { + // Derived from EPL + // See: https://esper.espertech.com/release-5.1.0/esper-reference/html/epl_clauses.html#epl-output-rate + public enum SCHEDULE_TYPE { ALL, FIRST, LAST, SNAPSHOT } + private Date start; private Date end; private String timeUnit; private long interval; private int repetitions; + private SCHEDULE_TYPE type; public long getIntervalInMillis() { if (timeUnit == null) return interval; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sensor.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sensor.java similarity index 77% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sensor.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sensor.java index b037f24..6423b09 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sensor.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sensor.java @@ -9,17 +9,23 @@ package gr.iccs.imu.ems.translate.model; +import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; +import java.util.LinkedHashMap; import java.util.Map; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Sensor extends Component { + @Builder.Default + private Map configuration = new LinkedHashMap<>(); private String configurationStr; private boolean isPush; @@ -34,14 +40,14 @@ public class Sensor extends Component { } public PullSensor pullSensor() { - if (this instanceof PullSensor) - return (PullSensor) this; + if (this instanceof PullSensor sensor) + return sensor; throw new IllegalArgumentException("Not a Pull sensor: " + this.getName()); } public PushSensor pushSensor() { - if (this instanceof PushSensor) - return (PushSensor) this; + if (this instanceof PushSensor sensor) + return sensor; throw new IllegalArgumentException("Not a Push sensor: " + this.getName()); } } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ServiceLevelObjective.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ServiceLevelObjective.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ServiceLevelObjective.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ServiceLevelObjective.java index 66f6861..e0f8d10 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ServiceLevelObjective.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ServiceLevelObjective.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class ServiceLevelObjective extends Requirement { // HardRequirement private Constraint constraint; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/SingleEvent.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/SingleEvent.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/SingleEvent.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/SingleEvent.java index a6f50be..d2798e0 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/SingleEvent.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/SingleEvent.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class SingleEvent extends Feature { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sink.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sink.java similarity index 95% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sink.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sink.java index 8d9d805..00a7920 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sink.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Sink.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.HashMap; @@ -20,6 +21,7 @@ import java.util.Map; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) // See: eu.melodic.models.interfaces.Sink public class Sink extends AbstractInterfaceRootObject { diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/StringValue.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/StringValue.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/StringValue.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/StringValue.java index e849300..d90081c 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/StringValue.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/StringValue.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class StringValue extends Value { private String value; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Timer.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Timer.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Timer.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Timer.java index 65e5f03..aa38fe6 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Timer.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Timer.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Timer extends Feature { private TimerType type; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/TimerType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/TimerType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/TimerType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/TimerType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryConstraint.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryConstraint.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryConstraint.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryConstraint.java index 6af266b..237e22e 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryConstraint.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryConstraint.java @@ -11,6 +11,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.Date; @@ -18,6 +19,7 @@ import java.util.Date; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class UnaryConstraint extends Constraint { private Date validity; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryEventPattern.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryEventPattern.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryEventPattern.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryEventPattern.java index 4bba0df..6bd8617 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryEventPattern.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryEventPattern.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class UnaryEventPattern extends EventPattern { private Event event; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryPatternOperatorType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryPatternOperatorType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryPatternOperatorType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/UnaryPatternOperatorType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Value.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Value.java similarity index 93% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Value.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Value.java index d14c1a4..0020b34 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Value.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Value.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Value extends AbstractRootObject { } diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ValueType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ValueType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ValueType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/ValueType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/VariableType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/VariableType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/VariableType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/VariableType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Window.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Window.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Window.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Window.java index c75b7ca..af8e7cd 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Window.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/Window.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.List; @@ -19,6 +20,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class Window extends Feature { private String timeUnit; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowCriterion.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowCriterion.java similarity index 94% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowCriterion.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowCriterion.java index cb5ee4b..36c6702 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowCriterion.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowCriterion.java @@ -11,11 +11,13 @@ package gr.iccs.imu.ems.translate.model; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class WindowCriterion extends NamedElement { private Metric metric; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessing.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessing.java similarity index 95% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessing.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessing.java index 94c89d1..4f1e234 100644 --- a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessing.java +++ b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessing.java @@ -12,6 +12,7 @@ package gr.iccs.imu.ems.translate.model; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import lombok.experimental.SuperBuilder; import java.util.ArrayList; @@ -20,6 +21,7 @@ import java.util.List; @lombok.Data @SuperBuilder @NoArgsConstructor +@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class WindowProcessing extends Feature { private WindowProcessingType processingType; diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessingType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessingType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessingType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowProcessingType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowSizeType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowSizeType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowSizeType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowSizeType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowType.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowType.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowType.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/model/WindowType.java diff --git a/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/mvv/MetricVariableValuesService.java b/nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/mvv/MetricVariableValuesService.java similarity index 100% rename from ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/mvv/MetricVariableValuesService.java rename to nebulous/ems-core/translator/src/main/java/gr/iccs/imu/ems/translate/mvv/MetricVariableValuesService.java diff --git a/ems-core/util/pom.xml b/nebulous/ems-core/util/pom.xml similarity index 98% rename from ems-core/util/pom.xml rename to nebulous/ems-core/util/pom.xml index f6c7658..b2d5823 100644 --- a/ems-core/util/pom.xml +++ b/nebulous/ems-core/util/pom.xml @@ -49,7 +49,7 @@ org.cryptacular cryptacular - 1.2.5 + ${cryptacular.version} diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/ClientConfiguration.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/ClientConfiguration.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/ClientConfiguration.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/ClientConfiguration.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMap.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMap.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMap.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMap.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMapConverter.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMapConverter.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMapConverter.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/CredentialsMapConverter.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/EmsConstant.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/EmsConstant.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/EmsConstant.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/EmsConstant.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/EventBus.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/EventBus.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/EventBus.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/EventBus.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/FunctionDefinition.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/FunctionDefinition.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/FunctionDefinition.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/FunctionDefinition.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/GROUPING.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/GROUPING.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/GROUPING.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/GROUPING.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/GroupingConfiguration.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/GroupingConfiguration.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/GroupingConfiguration.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/GroupingConfiguration.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/IKeystoreAndCertificateProperties.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/IKeystoreAndCertificateProperties.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/IKeystoreAndCertificateProperties.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/IKeystoreAndCertificateProperties.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreAndCertificateProperties.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreAndCertificateProperties.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreAndCertificateProperties.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreAndCertificateProperties.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreUtil.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreUtil.java similarity index 99% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreUtil.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreUtil.java index 89abddb..d812686 100644 --- a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreUtil.java +++ b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/KeystoreUtil.java @@ -228,8 +228,8 @@ public class KeystoreUtil { public KeystoreUtil createKeyAndCertWithSAN(String entryName, String dn) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, OperatorCreationException { - String sanExt = String.format("dns:localhost,ip:127.0.0.1,ip:%s,ip:%s", - NetUtil.getDefaultIpAddress(), NetUtil.getPublicIpAddress()); + String sanExt = "dns:localhost,ip:127.0.0.1,ip:%s,ip:%s" + .formatted(NetUtil.getDefaultIpAddress(), NetUtil.getPublicIpAddress()); return createKeyAndCert(entryName, dn, sanExt); } diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtil.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtil.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtil.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtil.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtilPostProcessor.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtilPostProcessor.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtilPostProcessor.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/NetUtilPostProcessor.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/PasswordUtil.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/PasswordUtil.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/PasswordUtil.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/PasswordUtil.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/Plugin.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/Plugin.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/Plugin.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/Plugin.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/SerializationUtil.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/SerializationUtil.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/SerializationUtil.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/SerializationUtil.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/StrUtil.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/StrUtil.java similarity index 99% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/StrUtil.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/StrUtil.java index 51d1f82..c1eb1f5 100644 --- a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/StrUtil.java +++ b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/StrUtil.java @@ -203,7 +203,7 @@ public class StrUtil { */ typeName = "unknown_type"; } - formatter = String.format("StrConverter: Invalid %s value: str=%s, Exception: ", typeName, str); + formatter = "StrConverter: Invalid %s value: str=%s, Exception: ".formatted(typeName, str); } log.warn(formatter, e); } diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/AsterisksPasswordEncoder.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/AsterisksPasswordEncoder.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/AsterisksPasswordEncoder.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/AsterisksPasswordEncoder.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/IdentityPasswordEncoder.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/IdentityPasswordEncoder.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/IdentityPasswordEncoder.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/IdentityPasswordEncoder.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PasswordEncoder.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PasswordEncoder.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PasswordEncoder.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PasswordEncoder.java diff --git a/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PresentPasswordEncoder.java b/nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PresentPasswordEncoder.java similarity index 100% rename from ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PresentPasswordEncoder.java rename to nebulous/ems-core/util/src/main/java/gr/iccs/imu/ems/util/password/PresentPasswordEncoder.java diff --git a/ems-core/web-admin/.dockerignore b/nebulous/ems-core/web-admin/.dockerignore similarity index 100% rename from ems-core/web-admin/.dockerignore rename to nebulous/ems-core/web-admin/.dockerignore diff --git a/ems-core/web-admin/.gitignore b/nebulous/ems-core/web-admin/.gitignore similarity index 100% rename from ems-core/web-admin/.gitignore rename to nebulous/ems-core/web-admin/.gitignore diff --git a/ems-core/web-admin/Dockerfile b/nebulous/ems-core/web-admin/Dockerfile similarity index 100% rename from ems-core/web-admin/Dockerfile rename to nebulous/ems-core/web-admin/Dockerfile diff --git a/ems-core/web-admin/README.md b/nebulous/ems-core/web-admin/README.md similarity index 100% rename from ems-core/web-admin/README.md rename to nebulous/ems-core/web-admin/README.md diff --git a/ems-core/web-admin/babel.config.js b/nebulous/ems-core/web-admin/babel.config.js similarity index 100% rename from ems-core/web-admin/babel.config.js rename to nebulous/ems-core/web-admin/babel.config.js diff --git a/ems-core/web-admin/package.json b/nebulous/ems-core/web-admin/package.json similarity index 100% rename from ems-core/web-admin/package.json rename to nebulous/ems-core/web-admin/package.json diff --git a/ems-core/web-admin/pom.xml b/nebulous/ems-core/web-admin/pom.xml similarity index 100% rename from ems-core/web-admin/pom.xml rename to nebulous/ems-core/web-admin/pom.xml diff --git a/ems-core/web-admin/public/assets/css/adminlte.min.css b/nebulous/ems-core/web-admin/public/assets/css/adminlte.min.css similarity index 100% rename from ems-core/web-admin/public/assets/css/adminlte.min.css rename to nebulous/ems-core/web-admin/public/assets/css/adminlte.min.css diff --git a/ems-core/web-admin/public/assets/img/circuit-board-5907811_1920-bw.png b/nebulous/ems-core/web-admin/public/assets/img/circuit-board-5907811_1920-bw.png similarity index 100% rename from ems-core/web-admin/public/assets/img/circuit-board-5907811_1920-bw.png rename to nebulous/ems-core/web-admin/public/assets/img/circuit-board-5907811_1920-bw.png diff --git a/ems-core/web-admin/public/assets/img/ems-logo-192x192.png b/nebulous/ems-core/web-admin/public/assets/img/ems-logo-192x192.png similarity index 100% rename from ems-core/web-admin/public/assets/img/ems-logo-192x192.png rename to nebulous/ems-core/web-admin/public/assets/img/ems-logo-192x192.png diff --git a/ems-core/web-admin/public/assets/img/wave-loader-green-sm.gif b/nebulous/ems-core/web-admin/public/assets/img/wave-loader-green-sm.gif similarity index 100% rename from ems-core/web-admin/public/assets/img/wave-loader-green-sm.gif rename to nebulous/ems-core/web-admin/public/assets/img/wave-loader-green-sm.gif diff --git a/ems-core/web-admin/public/assets/img/wave-loader-green.gif b/nebulous/ems-core/web-admin/public/assets/img/wave-loader-green.gif similarity index 100% rename from ems-core/web-admin/public/assets/img/wave-loader-green.gif rename to nebulous/ems-core/web-admin/public/assets/img/wave-loader-green.gif diff --git a/ems-core/web-admin/public/assets/img/wave-loader-grey-sm.gif b/nebulous/ems-core/web-admin/public/assets/img/wave-loader-grey-sm.gif similarity index 100% rename from ems-core/web-admin/public/assets/img/wave-loader-grey-sm.gif rename to nebulous/ems-core/web-admin/public/assets/img/wave-loader-grey-sm.gif diff --git a/ems-core/web-admin/public/assets/img/wave-loader-grey.gif b/nebulous/ems-core/web-admin/public/assets/img/wave-loader-grey.gif similarity index 100% rename from ems-core/web-admin/public/assets/img/wave-loader-grey.gif rename to nebulous/ems-core/web-admin/public/assets/img/wave-loader-grey.gif diff --git a/ems-core/web-admin/public/assets/js/adminlte.js b/nebulous/ems-core/web-admin/public/assets/js/adminlte.js similarity index 100% rename from ems-core/web-admin/public/assets/js/adminlte.js rename to nebulous/ems-core/web-admin/public/assets/js/adminlte.js diff --git a/ems-core/web-admin/public/assets/js/adminlte.js.map b/nebulous/ems-core/web-admin/public/assets/js/adminlte.js.map similarity index 100% rename from ems-core/web-admin/public/assets/js/adminlte.js.map rename to nebulous/ems-core/web-admin/public/assets/js/adminlte.js.map diff --git a/ems-core/web-admin/public/assets/js/adminlte.min.js b/nebulous/ems-core/web-admin/public/assets/js/adminlte.min.js similarity index 100% rename from ems-core/web-admin/public/assets/js/adminlte.min.js rename to nebulous/ems-core/web-admin/public/assets/js/adminlte.min.js diff --git a/ems-core/web-admin/public/assets/js/adminlte.min.js.map b/nebulous/ems-core/web-admin/public/assets/js/adminlte.min.js.map similarity index 100% rename from ems-core/web-admin/public/assets/js/adminlte.min.js.map rename to nebulous/ems-core/web-admin/public/assets/js/adminlte.min.js.map diff --git a/ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css diff --git a/ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css.map b/nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css.map similarity index 100% rename from ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css.map rename to nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/css/bootstrap.min.css.map diff --git a/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js b/nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js rename to nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js diff --git a/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js.map b/nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js.map similarity index 100% rename from ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js.map rename to nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.js.map diff --git a/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js diff --git a/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js.map b/nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js.map similarity index 100% rename from ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js.map rename to nebulous/ems-core/web-admin/public/assets/plugins/bootstrap/js/bootstrap.bundle.min.js.map diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/all.min.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/brands.min.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/fontawesome.min.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/regular.min.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/solid.min.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/svg-with-js.min.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.min.css b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.min.css similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.min.css rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/css/v4-shims.min.css diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/all.min.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/brands.min.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/conflict-detection.min.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/fontawesome.min.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/regular.min.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/solid.min.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/js/v4-shims.min.js diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.eot b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.eot similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.eot rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.eot diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.svg b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.svg similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.svg rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.svg diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.ttf b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.ttf similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.ttf rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.ttf diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff2 b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff2 similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff2 rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-brands-400.woff2 diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.eot b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.eot similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.eot rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.eot diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.svg b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.svg similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.svg rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.svg diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.ttf b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.ttf similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.ttf rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.ttf diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.eot b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.eot similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.eot rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.eot diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.svg b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.svg similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.svg rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.svg diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.ttf b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.ttf similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.ttf rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.ttf diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff diff --git a/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff2 b/nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff2 similarity index 100% rename from ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff2 rename to nebulous/ems-core/web-admin/public/assets/plugins/fontawesome-free/webfonts/fa-solid-900.woff2 diff --git a/ems-core/web-admin/public/assets/plugins/jquery/jquery.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/jquery/jquery.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/jquery/jquery.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/jquery/jquery.min.js diff --git a/ems-core/web-admin/public/assets/plugins/jquery/jquery.slimscroll.min.js b/nebulous/ems-core/web-admin/public/assets/plugins/jquery/jquery.slimscroll.min.js similarity index 100% rename from ems-core/web-admin/public/assets/plugins/jquery/jquery.slimscroll.min.js rename to nebulous/ems-core/web-admin/public/assets/plugins/jquery/jquery.slimscroll.min.js diff --git a/ems-core/web-admin/public/favicon.ico b/nebulous/ems-core/web-admin/public/favicon.ico similarity index 100% rename from ems-core/web-admin/public/favicon.ico rename to nebulous/ems-core/web-admin/public/favicon.ico diff --git a/ems-core/web-admin/public/index.html b/nebulous/ems-core/web-admin/public/index.html similarity index 100% rename from ems-core/web-admin/public/index.html rename to nebulous/ems-core/web-admin/public/index.html diff --git a/ems-core/web-admin/public/login.html b/nebulous/ems-core/web-admin/public/login.html similarity index 100% rename from ems-core/web-admin/public/login.html rename to nebulous/ems-core/web-admin/public/login.html diff --git a/ems-core/web-admin/src/App.vue b/nebulous/ems-core/web-admin/src/App.vue similarity index 100% rename from ems-core/web-admin/src/App.vue rename to nebulous/ems-core/web-admin/src/App.vue diff --git a/ems-core/web-admin/src/assets/img/backgrounds/circuit-board-5907811_1920-bw.png b/nebulous/ems-core/web-admin/src/assets/img/backgrounds/circuit-board-5907811_1920-bw.png similarity index 100% rename from ems-core/web-admin/src/assets/img/backgrounds/circuit-board-5907811_1920-bw.png rename to nebulous/ems-core/web-admin/src/assets/img/backgrounds/circuit-board-5907811_1920-bw.png diff --git a/ems-core/web-admin/src/assets/img/ems-logo-192x192.png b/nebulous/ems-core/web-admin/src/assets/img/ems-logo-192x192.png similarity index 100% rename from ems-core/web-admin/src/assets/img/ems-logo-192x192.png rename to nebulous/ems-core/web-admin/src/assets/img/ems-logo-192x192.png diff --git a/ems-core/web-admin/src/assets/img/ems-logo.png b/nebulous/ems-core/web-admin/src/assets/img/ems-logo.png similarity index 100% rename from ems-core/web-admin/src/assets/img/ems-logo.png rename to nebulous/ems-core/web-admin/src/assets/img/ems-logo.png diff --git a/ems-core/web-admin/src/assets/img/ems-logo.svg b/nebulous/ems-core/web-admin/src/assets/img/ems-logo.svg similarity index 100% rename from ems-core/web-admin/src/assets/img/ems-logo.svg rename to nebulous/ems-core/web-admin/src/assets/img/ems-logo.svg diff --git a/ems-core/web-admin/src/assets/img/party.gif b/nebulous/ems-core/web-admin/src/assets/img/party.gif similarity index 100% rename from ems-core/web-admin/src/assets/img/party.gif rename to nebulous/ems-core/web-admin/src/assets/img/party.gif diff --git a/ems-core/web-admin/src/components/7seg/7seg.vue b/nebulous/ems-core/web-admin/src/components/7seg/7seg.vue similarity index 100% rename from ems-core/web-admin/src/components/7seg/7seg.vue rename to nebulous/ems-core/web-admin/src/components/7seg/7seg.vue diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Bold.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Bold.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Bold.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Bold.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-BoldItalic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-BoldItalic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-BoldItalic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-BoldItalic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Italic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Italic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Italic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Italic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Regular.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Regular.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Regular.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Classic/DSEG14Classic-Regular.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Bold.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Bold.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Bold.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Bold.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-BoldItalic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-BoldItalic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-BoldItalic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-BoldItalic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Italic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Italic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Italic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Italic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Regular.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Regular.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Regular.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG14-Modern/DSEG14Modern-Regular.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Bold.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Bold.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Bold.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Bold.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-BoldItalic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-BoldItalic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-BoldItalic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-BoldItalic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Italic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Italic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Italic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Italic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Regular.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Regular.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Regular.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Classic/DSEG7Classic-Regular.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Bold.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Bold.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Bold.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Bold.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-BoldItalic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-BoldItalic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-BoldItalic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-BoldItalic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Italic.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Italic.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Italic.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Italic.woff2 diff --git a/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Regular.woff2 b/nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Regular.woff2 similarity index 100% rename from ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Regular.woff2 rename to nebulous/ems-core/web-admin/src/components/7seg/DSEG7-Modern/DSEG7Modern-Regular.woff2 diff --git a/ems-core/web-admin/src/components/ace-editor/ace-editor.vue b/nebulous/ems-core/web-admin/src/components/ace-editor/ace-editor.vue similarity index 100% rename from ems-core/web-admin/src/components/ace-editor/ace-editor.vue rename to nebulous/ems-core/web-admin/src/components/ace-editor/ace-editor.vue diff --git a/ems-core/web-admin/src/components/card/card.html b/nebulous/ems-core/web-admin/src/components/card/card.html similarity index 100% rename from ems-core/web-admin/src/components/card/card.html rename to nebulous/ems-core/web-admin/src/components/card/card.html diff --git a/ems-core/web-admin/src/components/card/card.js b/nebulous/ems-core/web-admin/src/components/card/card.js similarity index 100% rename from ems-core/web-admin/src/components/card/card.js rename to nebulous/ems-core/web-admin/src/components/card/card.js diff --git a/ems-core/web-admin/src/components/card/card.vue b/nebulous/ems-core/web-admin/src/components/card/card.vue similarity index 100% rename from ems-core/web-admin/src/components/card/card.vue rename to nebulous/ems-core/web-admin/src/components/card/card.vue diff --git a/ems-core/web-admin/src/components/chartjs/chartjs.vue b/nebulous/ems-core/web-admin/src/components/chartjs/chartjs.vue similarity index 100% rename from ems-core/web-admin/src/components/chartjs/chartjs.vue rename to nebulous/ems-core/web-admin/src/components/chartjs/chartjs.vue diff --git a/ems-core/web-admin/src/components/clock/clock.vue b/nebulous/ems-core/web-admin/src/components/clock/clock.vue similarity index 100% rename from ems-core/web-admin/src/components/clock/clock.vue rename to nebulous/ems-core/web-admin/src/components/clock/clock.vue diff --git a/ems-core/web-admin/src/components/ems/sse/ems-sse.vue b/nebulous/ems-core/web-admin/src/components/ems/sse/ems-sse.vue similarity index 100% rename from ems-core/web-admin/src/components/ems/sse/ems-sse.vue rename to nebulous/ems-core/web-admin/src/components/ems/sse/ems-sse.vue diff --git a/ems-core/web-admin/src/components/ems/ts/ts.js b/nebulous/ems-core/web-admin/src/components/ems/ts/ts.js similarity index 100% rename from ems-core/web-admin/src/components/ems/ts/ts.js rename to nebulous/ems-core/web-admin/src/components/ems/ts/ts.js diff --git a/ems-core/web-admin/src/components/infobox/infobox.html b/nebulous/ems-core/web-admin/src/components/infobox/infobox.html similarity index 100% rename from ems-core/web-admin/src/components/infobox/infobox.html rename to nebulous/ems-core/web-admin/src/components/infobox/infobox.html diff --git a/ems-core/web-admin/src/components/infobox/infobox.js b/nebulous/ems-core/web-admin/src/components/infobox/infobox.js similarity index 100% rename from ems-core/web-admin/src/components/infobox/infobox.js rename to nebulous/ems-core/web-admin/src/components/infobox/infobox.js diff --git a/ems-core/web-admin/src/components/infobox/infobox.vue b/nebulous/ems-core/web-admin/src/components/infobox/infobox.vue similarity index 100% rename from ems-core/web-admin/src/components/infobox/infobox.vue rename to nebulous/ems-core/web-admin/src/components/infobox/infobox.vue diff --git a/ems-core/web-admin/src/components/jqvmap/jqvmap.vue b/nebulous/ems-core/web-admin/src/components/jqvmap/jqvmap.vue similarity index 100% rename from ems-core/web-admin/src/components/jqvmap/jqvmap.vue rename to nebulous/ems-core/web-admin/src/components/jqvmap/jqvmap.vue diff --git a/ems-core/web-admin/src/components/jvectormap/jvectormap.vue b/nebulous/ems-core/web-admin/src/components/jvectormap/jvectormap.vue similarity index 100% rename from ems-core/web-admin/src/components/jvectormap/jvectormap.vue rename to nebulous/ems-core/web-admin/src/components/jvectormap/jvectormap.vue diff --git a/ems-core/web-admin/src/components/knob/knob.vue b/nebulous/ems-core/web-admin/src/components/knob/knob.vue similarity index 100% rename from ems-core/web-admin/src/components/knob/knob.vue rename to nebulous/ems-core/web-admin/src/components/knob/knob.vue diff --git a/ems-core/web-admin/src/components/leaflet-map/leaflet-map.vue b/nebulous/ems-core/web-admin/src/components/leaflet-map/leaflet-map.vue similarity index 100% rename from ems-core/web-admin/src/components/leaflet-map/leaflet-map.vue rename to nebulous/ems-core/web-admin/src/components/leaflet-map/leaflet-map.vue diff --git a/ems-core/web-admin/src/components/modal/modal.vue b/nebulous/ems-core/web-admin/src/components/modal/modal.vue similarity index 100% rename from ems-core/web-admin/src/components/modal/modal.vue rename to nebulous/ems-core/web-admin/src/components/modal/modal.vue diff --git a/ems-core/web-admin/src/components/smallbox/smallbox.html b/nebulous/ems-core/web-admin/src/components/smallbox/smallbox.html similarity index 100% rename from ems-core/web-admin/src/components/smallbox/smallbox.html rename to nebulous/ems-core/web-admin/src/components/smallbox/smallbox.html diff --git a/ems-core/web-admin/src/components/smallbox/smallbox.js b/nebulous/ems-core/web-admin/src/components/smallbox/smallbox.js similarity index 100% rename from ems-core/web-admin/src/components/smallbox/smallbox.js rename to nebulous/ems-core/web-admin/src/components/smallbox/smallbox.js diff --git a/ems-core/web-admin/src/components/smallbox/smallbox.vue b/nebulous/ems-core/web-admin/src/components/smallbox/smallbox.vue similarity index 100% rename from ems-core/web-admin/src/components/smallbox/smallbox.vue rename to nebulous/ems-core/web-admin/src/components/smallbox/smallbox.vue diff --git a/ems-core/web-admin/src/components/sparkline/sparkline.vue b/nebulous/ems-core/web-admin/src/components/sparkline/sparkline.vue similarity index 100% rename from ems-core/web-admin/src/components/sparkline/sparkline.vue rename to nebulous/ems-core/web-admin/src/components/sparkline/sparkline.vue diff --git a/ems-core/web-admin/src/components/status-led/status-led.vue b/nebulous/ems-core/web-admin/src/components/status-led/status-led.vue similarity index 100% rename from ems-core/web-admin/src/components/status-led/status-led.vue rename to nebulous/ems-core/web-admin/src/components/status-led/status-led.vue diff --git a/ems-core/web-admin/src/components/worldmap/WorldMap.vue b/nebulous/ems-core/web-admin/src/components/worldmap/WorldMap.vue similarity index 100% rename from ems-core/web-admin/src/components/worldmap/WorldMap.vue rename to nebulous/ems-core/web-admin/src/components/worldmap/WorldMap.vue diff --git a/ems-core/web-admin/src/components/worldmap/countries.js b/nebulous/ems-core/web-admin/src/components/worldmap/countries.js similarity index 100% rename from ems-core/web-admin/src/components/worldmap/countries.js rename to nebulous/ems-core/web-admin/src/components/worldmap/countries.js diff --git a/ems-core/web-admin/src/main.js b/nebulous/ems-core/web-admin/src/main.js similarity index 100% rename from ems-core/web-admin/src/main.js rename to nebulous/ems-core/web-admin/src/main.js diff --git a/ems-core/web-admin/src/resources/.env b/nebulous/ems-core/web-admin/src/resources/.env similarity index 100% rename from ems-core/web-admin/src/resources/.env rename to nebulous/ems-core/web-admin/src/resources/.env diff --git a/ems-core/web-admin/src/router.js b/nebulous/ems-core/web-admin/src/router.js similarity index 100% rename from ems-core/web-admin/src/router.js rename to nebulous/ems-core/web-admin/src/router.js diff --git a/ems-core/web-admin/src/utils.js b/nebulous/ems-core/web-admin/src/utils.js similarity index 100% rename from ems-core/web-admin/src/utils.js rename to nebulous/ems-core/web-admin/src/utils.js diff --git a/ems-core/web-admin/src/views/404.vue b/nebulous/ems-core/web-admin/src/views/404.vue similarity index 100% rename from ems-core/web-admin/src/views/404.vue rename to nebulous/ems-core/web-admin/src/views/404.vue diff --git a/ems-core/web-admin/src/views/about.vue b/nebulous/ems-core/web-admin/src/views/about.vue similarity index 100% rename from ems-core/web-admin/src/views/about.vue rename to nebulous/ems-core/web-admin/src/views/about.vue diff --git a/ems-core/web-admin/src/views/admin/admin-1-overview-header.vue b/nebulous/ems-core/web-admin/src/views/admin/admin-1-overview-header.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/admin-1-overview-header.vue rename to nebulous/ems-core/web-admin/src/views/admin/admin-1-overview-header.vue diff --git a/ems-core/web-admin/src/views/admin/admin-1-overview.vue b/nebulous/ems-core/web-admin/src/views/admin/admin-1-overview.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/admin-1-overview.vue rename to nebulous/ems-core/web-admin/src/views/admin/admin-1-overview.vue diff --git a/ems-core/web-admin/src/views/admin/admin-1-overview.vue.old b/nebulous/ems-core/web-admin/src/views/admin/admin-1-overview.vue.old similarity index 100% rename from ems-core/web-admin/src/views/admin/admin-1-overview.vue.old rename to nebulous/ems-core/web-admin/src/views/admin/admin-1-overview.vue.old diff --git a/ems-core/web-admin/src/views/admin/admin-2-topology.vue b/nebulous/ems-core/web-admin/src/views/admin/admin-2-topology.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/admin-2-topology.vue rename to nebulous/ems-core/web-admin/src/views/admin/admin-2-topology.vue diff --git a/ems-core/web-admin/src/views/admin/admin-3-geography.vue b/nebulous/ems-core/web-admin/src/views/admin/admin-3-geography.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/admin-3-geography.vue rename to nebulous/ems-core/web-admin/src/views/admin/admin-3-geography.vue diff --git a/ems-core/web-admin/src/views/admin/admin-4-commands.vue b/nebulous/ems-core/web-admin/src/views/admin/admin-4-commands.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/admin-4-commands.vue rename to nebulous/ems-core/web-admin/src/views/admin/admin-4-commands.vue diff --git a/ems-core/web-admin/src/views/admin/admin-5-broker-cep.vue b/nebulous/ems-core/web-admin/src/views/admin/admin-5-broker-cep.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/admin-5-broker-cep.vue rename to nebulous/ems-core/web-admin/src/views/admin/admin-5-broker-cep.vue diff --git a/ems-core/web-admin/src/views/admin/admin.vue b/nebulous/ems-core/web-admin/src/views/admin/admin.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/admin.vue rename to nebulous/ems-core/web-admin/src/views/admin/admin.vue diff --git a/ems-core/web-admin/src/views/admin/country-coordinates.js b/nebulous/ems-core/web-admin/src/views/admin/country-coordinates.js similarity index 100% rename from ems-core/web-admin/src/views/admin/country-coordinates.js rename to nebulous/ems-core/web-admin/src/views/admin/country-coordinates.js diff --git a/ems-core/web-admin/src/views/admin/old/admin.html b/nebulous/ems-core/web-admin/src/views/admin/old/admin.html similarity index 100% rename from ems-core/web-admin/src/views/admin/old/admin.html rename to nebulous/ems-core/web-admin/src/views/admin/old/admin.html diff --git a/ems-core/web-admin/src/views/admin/old/admin.js b/nebulous/ems-core/web-admin/src/views/admin/old/admin.js similarity index 100% rename from ems-core/web-admin/src/views/admin/old/admin.js rename to nebulous/ems-core/web-admin/src/views/admin/old/admin.js diff --git a/ems-core/web-admin/src/views/admin/old/admin.vue b/nebulous/ems-core/web-admin/src/views/admin/old/admin.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/old/admin.vue rename to nebulous/ems-core/web-admin/src/views/admin/old/admin.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/cdo-mgnt.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/cdo-mgnt.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/cdo-mgnt.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/cdo-mgnt.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/client-commands.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/client-commands.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/client-commands.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/client-commands.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/client-events.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/client-events.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/client-events.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/client-events.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/clients-list.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/clients-list.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/clients-list.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/clients-list.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/command-input.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/command-input.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/command-input.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/command-input.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/destinations-list.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/destinations-list.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/destinations-list.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/destinations-list.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/fileexplorer.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/fileexplorer.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/fileexplorer.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/fileexplorer.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/img/blank-64.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/blank-64.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/blank-64.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/blank-64.png diff --git a/ems-core/web-admin/src/views/admin/widgets/img/camel-model-32.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/camel-model-32.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/camel-model-32.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/camel-model-32.png diff --git a/ems-core/web-admin/src/views/admin/widgets/img/camel-model-64.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/camel-model-64.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/camel-model-64.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/camel-model-64.png diff --git a/ems-core/web-admin/src/views/admin/widgets/img/camel-model-80.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/camel-model-80.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/camel-model-80.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/camel-model-80.png diff --git a/ems-core/web-admin/src/views/admin/widgets/img/cp-model-32.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/cp-model-32.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/cp-model-32.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/cp-model-32.png diff --git a/ems-core/web-admin/src/views/admin/widgets/img/cp-model-64.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/cp-model-64.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/cp-model-64.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/cp-model-64.png diff --git a/ems-core/web-admin/src/views/admin/widgets/img/folder-64.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/folder-64.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/folder-64.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/folder-64.png diff --git a/ems-core/web-admin/src/views/admin/widgets/img/unknown-64.png b/nebulous/ems-core/web-admin/src/views/admin/widgets/img/unknown-64.png similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/img/unknown-64.png rename to nebulous/ems-core/web-admin/src/views/admin/widgets/img/unknown-64.png diff --git a/ems-core/web-admin/src/views/admin/widgets/latest-events.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/latest-events.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/latest-events.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/latest-events.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/node-actions-list.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/node-actions-list.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/node-actions-list.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/node-actions-list.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/rest-call-forms.js b/nebulous/ems-core/web-admin/src/views/admin/widgets/rest-call-forms.js similarity index 88% rename from ems-core/web-admin/src/views/admin/widgets/rest-call-forms.js rename to nebulous/ems-core/web-admin/src/views/admin/widgets/rest-call-forms.js index ec138f8..e322996 100644 --- a/ems-core/web-admin/src/views/admin/widgets/rest-call-forms.js +++ b/nebulous/ems-core/web-admin/src/views/admin/widgets/rest-call-forms.js @@ -13,11 +13,12 @@ export const FORM_TYPE_OPTIONS = [ 'text': 'Basic API - Model Translation', 'priority': -1000, 'options': [ - { 'id': 'new-app-model', 'text': 'Send App. model request', 'url': '/camelModel', 'method': 'POST', 'form': 'app-model-form', 'priority': 1 }, - { 'id': 'new-cp-model', 'text': 'Send CP model request', 'url': '/cpModelJson', 'method': 'POST', 'form': 'cp-model-form', 'priority': 2 }, - { 'id': 'constants-update', 'text': 'Set constants (add name-value pairs in Payload)', 'url': '/cpConstants', 'method': 'POST', 'form': '', 'priority': 3 }, + { 'id': 'new-app-model', 'text': 'Send App. model request', 'url': '/appModel', 'method': 'POST', 'form': 'app-model-form', 'priority': 1 }, + { 'id': 'new-app-exec-model', 'text': 'Send App. Execution model request', 'url': '/appExecModel', 'method': 'POST', 'form': 'app-exec-model-form', 'priority': 2 }, + { 'id': 'constants-update', 'text': 'Set constants (add name-value pairs in Payload)', 'url': '/appConstants', 'method': 'POST', 'form': '', 'priority': 3 }, { 'id': 'get-app-model', 'text': 'Current App. model', 'url': '/translator/currentAppModel', 'method': 'GET', 'form': '', 'priority': 4 }, - { 'id': 'get-cp-model', 'text': 'Current CP model', 'url': '/translator/currentCpModel', 'method': 'GET', 'form': '', 'priority': 5 }, + { 'id': 'get-app-exec-model', 'text': 'Current App. Execution model', 'url': '/translator/currentAppExecModel', 'method': 'GET', 'form': '', 'priority': 5 }, + { 'id': 'get-curr-tc', 'text': 'Current Translation Context', 'url': '/translator/currentTranslationContext', 'method': 'GET', 'form': '', 'priority': 6 }, ] }, @@ -71,7 +72,7 @@ export const FORM_TYPE_OPTIONS = [ 'options': [ { 'id': 'd-stop-baguette', 'text': 'Stop Baguette Server', 'url': '/baguette/stopServer', 'method': 'GET', 'form': '', 'priority': 1 }, { 'id': 'd-shutdown', 'text': 'EMS server shutdown', 'url': '/ems/shutdown', 'method': 'GET', 'form': '', 'priority': 2 }, - { 'id': 'd-exit', 'text': 'EMS server shutdown and Exit', 'url': '/ems/exit', 'method': 'GET', 'form': '', 'priority': 3 }, + { 'id': 'd-exit', 'text': 'EMS server shutdown and Exit', 'url': '/ems/exit/0', 'method': 'GET', 'form': '', 'priority': 3 }, { 'id': 'd-restart', 'text': 'EMS server shutdown and Restart', 'url': '/ems/exit/99', 'method': 'GET', 'form': '', 'priority': 4 } ] } @@ -89,9 +90,9 @@ export const FORM_SPECS = { { 'name': 'watermark.date', 'text': '-- Date', 'defaultValue': function() { return new Date().getTime(); } }, ], }, - 'cp-model-form': { + 'app-exec-model-form': { 'fields': [ - { 'name': 'cp-model-id', 'text': 'CP model path' }, + { 'name': 'app-exec-model-id', 'text': 'App. Execution model path' }, ] }, 'vm-form': { diff --git a/ems-core/web-admin/src/views/admin/widgets/rest-call.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/rest-call.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/rest-call.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/rest-call.vue diff --git a/ems-core/web-admin/src/views/admin/widgets/textarea-dnd.vue b/nebulous/ems-core/web-admin/src/views/admin/widgets/textarea-dnd.vue similarity index 100% rename from ems-core/web-admin/src/views/admin/widgets/textarea-dnd.vue rename to nebulous/ems-core/web-admin/src/views/admin/widgets/textarea-dnd.vue diff --git a/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.html b/nebulous/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.html similarity index 100% rename from ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.html rename to nebulous/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.html diff --git a/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.js b/nebulous/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.js similarity index 100% rename from ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.js rename to nebulous/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.js diff --git a/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.vue b/nebulous/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.vue similarity index 100% rename from ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.vue rename to nebulous/ems-core/web-admin/src/views/common/control-sidebar/control-sidebar.vue diff --git a/ems-core/web-admin/src/views/common/footer/footer.html b/nebulous/ems-core/web-admin/src/views/common/footer/footer.html similarity index 100% rename from ems-core/web-admin/src/views/common/footer/footer.html rename to nebulous/ems-core/web-admin/src/views/common/footer/footer.html diff --git a/ems-core/web-admin/src/views/common/footer/footer.js b/nebulous/ems-core/web-admin/src/views/common/footer/footer.js similarity index 100% rename from ems-core/web-admin/src/views/common/footer/footer.js rename to nebulous/ems-core/web-admin/src/views/common/footer/footer.js diff --git a/ems-core/web-admin/src/views/common/footer/footer.vue b/nebulous/ems-core/web-admin/src/views/common/footer/footer.vue similarity index 100% rename from ems-core/web-admin/src/views/common/footer/footer.vue rename to nebulous/ems-core/web-admin/src/views/common/footer/footer.vue diff --git a/ems-core/web-admin/src/views/common/header/header.html b/nebulous/ems-core/web-admin/src/views/common/header/header.html similarity index 97% rename from ems-core/web-admin/src/views/common/header/header.html rename to nebulous/ems-core/web-admin/src/views/common/header/header.html index 6e3ccad..982acc5 100644 --- a/ems-core/web-admin/src/views/common/header/header.html +++ b/nebulous/ems-core/web-admin/src/views/common/header/header.html @@ -25,7 +25,7 @@ Log viewer Old EMS Server logs - Translation context + Translation context DAG as...     {{item.slice(item.lastIndexOf('.')+1).toLowerCase()}} diff --git a/ems-core/web-admin/src/views/common/header/header.js b/nebulous/ems-core/web-admin/src/views/common/header/header.js similarity index 100% rename from ems-core/web-admin/src/views/common/header/header.js rename to nebulous/ems-core/web-admin/src/views/common/header/header.js diff --git a/ems-core/web-admin/src/views/common/header/header.vue b/nebulous/ems-core/web-admin/src/views/common/header/header.vue similarity index 100% rename from ems-core/web-admin/src/views/common/header/header.vue rename to nebulous/ems-core/web-admin/src/views/common/header/header.vue diff --git a/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.html b/nebulous/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.html similarity index 100% rename from ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.html rename to nebulous/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.html diff --git a/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.js b/nebulous/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.js similarity index 100% rename from ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.js rename to nebulous/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.js diff --git a/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.vue b/nebulous/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.vue similarity index 100% rename from ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.vue rename to nebulous/ems-core/web-admin/src/views/common/menu-sidebar/menu-sidebar.vue diff --git a/ems-core/web-admin/src/views/common/section/section.vue b/nebulous/ems-core/web-admin/src/views/common/section/section.vue similarity index 100% rename from ems-core/web-admin/src/views/common/section/section.vue rename to nebulous/ems-core/web-admin/src/views/common/section/section.vue diff --git a/ems-core/web-admin/src/views/common/title-and-breadcrumb/title-and-breadcrumb.vue b/nebulous/ems-core/web-admin/src/views/common/title-and-breadcrumb/title-and-breadcrumb.vue similarity index 100% rename from ems-core/web-admin/src/views/common/title-and-breadcrumb/title-and-breadcrumb.vue rename to nebulous/ems-core/web-admin/src/views/common/title-and-breadcrumb/title-and-breadcrumb.vue diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/connection-info.vue b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/connection-info.vue similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/connection-info.vue rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/connection-info.vue diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-blue.png b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-blue.png similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-blue.png rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-blue.png diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-green.png b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-green.png similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-green.png rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-green.png diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-orange.png b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-orange.png similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-orange.png rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-orange.png diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-red.png b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-red.png similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-red.png rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/plug-red.png diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-blue.gif b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-blue.gif similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-blue.gif rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-blue.gif diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-green.gif b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-green.gif similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-green.gif rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-green.gif diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-orange.gif b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-orange.gif similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-orange.gif rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-orange.gif diff --git a/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-red.gif b/nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-red.gif similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-red.gif rename to nebulous/ems-core/web-admin/src/views/common/widgets/connection-info/img/wave-red.gif diff --git a/ems-core/web-admin/src/views/common/widgets/health-info/health-info.vue b/nebulous/ems-core/web-admin/src/views/common/widgets/health-info/health-info.vue similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/health-info/health-info.vue rename to nebulous/ems-core/web-admin/src/views/common/widgets/health-info/health-info.vue diff --git a/ems-core/web-admin/src/views/common/widgets/notifications/notifications.html b/nebulous/ems-core/web-admin/src/views/common/widgets/notifications/notifications.html similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/notifications/notifications.html rename to nebulous/ems-core/web-admin/src/views/common/widgets/notifications/notifications.html diff --git a/ems-core/web-admin/src/views/common/widgets/notifications/notifications.js b/nebulous/ems-core/web-admin/src/views/common/widgets/notifications/notifications.js similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/notifications/notifications.js rename to nebulous/ems-core/web-admin/src/views/common/widgets/notifications/notifications.js diff --git a/ems-core/web-admin/src/views/common/widgets/notifications/notifications.vue b/nebulous/ems-core/web-admin/src/views/common/widgets/notifications/notifications.vue similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/notifications/notifications.vue rename to nebulous/ems-core/web-admin/src/views/common/widgets/notifications/notifications.vue diff --git a/ems-core/web-admin/src/views/common/widgets/search/search.vue b/nebulous/ems-core/web-admin/src/views/common/widgets/search/search.vue similarity index 100% rename from ems-core/web-admin/src/views/common/widgets/search/search.vue rename to nebulous/ems-core/web-admin/src/views/common/widgets/search/search.vue diff --git a/ems-core/web-admin/src/views/sample/sample.html b/nebulous/ems-core/web-admin/src/views/sample/sample.html similarity index 100% rename from ems-core/web-admin/src/views/sample/sample.html rename to nebulous/ems-core/web-admin/src/views/sample/sample.html diff --git a/ems-core/web-admin/src/views/sample/sample.js b/nebulous/ems-core/web-admin/src/views/sample/sample.js similarity index 100% rename from ems-core/web-admin/src/views/sample/sample.js rename to nebulous/ems-core/web-admin/src/views/sample/sample.js diff --git a/ems-core/web-admin/src/views/sample/sample.vue b/nebulous/ems-core/web-admin/src/views/sample/sample.vue similarity index 100% rename from ems-core/web-admin/src/views/sample/sample.vue rename to nebulous/ems-core/web-admin/src/views/sample/sample.vue diff --git a/ems-core/web-admin/vue.config.js b/nebulous/ems-core/web-admin/vue.config.js similarity index 100% rename from ems-core/web-admin/vue.config.js rename to nebulous/ems-core/web-admin/vue.config.js diff --git a/nebulous/ems-nebulous/.gitattributes b/nebulous/ems-nebulous/.gitattributes new file mode 100644 index 0000000..d54d7b5 --- /dev/null +++ b/nebulous/ems-nebulous/.gitattributes @@ -0,0 +1,12 @@ +# +# Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) +# +# This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. +# If a copy of the MPL was not distributed with this file, You can obtain one at +# https://www.mozilla.org/en-US/MPL/2.0/ +# + +*.sh text eol=lf +*.xml text eol=lf +.gitignore text eol=lf +.gitattributes text eol=lf \ No newline at end of file diff --git a/nebulous/ems-nebulous/.gitignore b/nebulous/ems-nebulous/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/nebulous/ems-nebulous/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/nebulous/ems-nebulous/LICENSE b/nebulous/ems-nebulous/LICENSE new file mode 100644 index 0000000..d0a1fa1 --- /dev/null +++ b/nebulous/ems-nebulous/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/nebulous/ems-nebulous/pom.xml b/nebulous/ems-nebulous/pom.xml new file mode 100644 index 0000000..d99fe65 --- /dev/null +++ b/nebulous/ems-nebulous/pom.xml @@ -0,0 +1,316 @@ + + + + 4.0.0 + + eu.nebulous.ems + ems-nebulous-plugin + 1.0.0-SNAPSHOT + jar + Nebulous-EMS plugin + Nebulous-EMS plugin provides metric model translator and MVV service + + + 21 + 21 + 21 + UTF-8 + + + 7.0.0-SNAPSHOT + + + 6.1.2 + 3.2.1 + 2.2 + 1.18.30 + + + 2.16.0 + 2.8.0 + 3.1.2.RELEASE + 7.1.3 + + + ../ems-core/control-service/target/docker-image.properties + 0.43.2 + + + + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + + + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + org.springframework.boot + spring-boot-starter + ${spring-boot.version} + provided + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + provided + + + org.springframework.boot + spring-boot-starter-webflux + ${spring-boot.version} + provided + + + + org.springframework + spring-context-indexer + ${spring.version} + true + + + + + gr.iccs.imu.ems + util + ${ems.version} + provided + + + gr.iccs.imu.ems + broker-cep + ${ems.version} + provided + + + gr.iccs.imu.ems + translator + ${ems.version} + provided + + + gr.iccs.imu.ems + control-service + ${ems.version} + original + provided + + + + + + + com.jayway.jsonpath + json-path + ${json-path.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + + + + + org.thymeleaf + thymeleaf-spring6 + ${thymeleaf.version} + + + + + com.helger.schematron + ph-schematron-api + ${schematron.version} + + + com.helger.schematron + ph-schematron-xslt + ${schematron.version} + + + com.helger.schematron + ph-schematron-pure + ${schematron.version} + + + com.helger.schematron + ph-schematron-validator + ${schematron.version} + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + maven-antrun-plugin + 3.1.0 + + + remove-slf4j-files-from-jar-with-dependencies + package + + + + + + + + + + + run + + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.2.0 + + + read-docker-image-properties + validate + + read-project-properties + + + + + + + ${docker-image-properties-file} + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionInfoBeaconPlugin.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionInfoBeaconPlugin.java new file mode 100644 index 0000000..fc32f83 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionInfoBeaconPlugin.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.plugins; + +import gr.iccs.imu.ems.control.plugin.BeaconPlugin; +import gr.iccs.imu.ems.control.properties.TopicBeaconProperties; +import gr.iccs.imu.ems.control.util.TopicBeacon; +import gr.iccs.imu.ems.translate.TranslationContext; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import jakarta.jms.JMSException; +import java.util.Collections; +import java.util.Set; + +@Slf4j +@Service +public class PredictionInfoBeaconPlugin implements BeaconPlugin { + public void transmit(TopicBeacon.BeaconContext context) { + log.debug("PredictionInfoBeaconPlugin.transmit(): Invoked"); + transmitPredictionInfo(context); + transmitSloViolatorInfo(context); + } + + private Set emptyIfNull(Set s) { + if (s==null) return Collections.emptySet(); + return s; + } + + public void transmitPredictionInfo(TopicBeacon.BeaconContext context) { + TopicBeaconProperties properties = context.getProperties(); + if (emptyIfNull(properties.getPredictionTopics()).isEmpty()) return; + + // Get TranslationContext for current model + String modelId = context.getCurrentAppModelId(); + log.trace("Topic Beacon: transmitPredictionInfo: app-model-id: {}", modelId); + TranslationContext translationContext = context.getTranslationContextOfAppModel(modelId); + if (translationContext==null) { + log.trace("Topic Beacon: transmitPredictionInfo: No TranslationContext for app-model-id: {}", modelId); + return; + } + + //Set topLevelMetrics = coordinator.getGlobalGroupingMetrics(modelId); + //log.debug("Topic Beacon: transmitPredictionInfo: DAG Global-Level Metrics: {}", topLevelMetrics); + + // Get metric contexts of top-level DAG nodes + String metricContexts = translationContext.getAdditionalResultsAs( + PredictionsPostTranslationPlugin.PREDICTION_TOP_LEVEL_NODES_METRICS, String.class); + log.debug("Topic Beacon: transmitPredictionInfo: Metric Contexts for prediction: {}", metricContexts); + + // Skip event sending if payload is empty + if (StringUtils.isBlank(metricContexts)) { + log.debug("Topic Beacon: transmitSloViolatorInfo: Payload is empty. Not sending event"); + return; + } + + // Send event with payload + log.debug("Topic Beacon: Transmitting Prediction info: event={}, topics={}", metricContexts, properties.getPredictionTopics()); + try { + context.sendMessageToTopics(metricContexts, properties.getPredictionTopics()); + } catch (JMSException e) { + log.error("Topic Beacon: EXCEPTION while transmitting Prediction info: event={}, topics={}, exception: ", + metricContexts, properties.getPredictionTopics(), e); + } + } + + public void transmitSloViolatorInfo(TopicBeacon.BeaconContext context) { + TopicBeaconProperties properties = context.getProperties(); + if (emptyIfNull(properties.getSloViolationDetectorTopics()).isEmpty()) return; + + // Get TranslationContext for current model + String modelId = context.getCurrentAppModelId(); + log.trace("Topic Beacon: transmitSloViolatorInfo: current-app-model-id: {}", modelId); + TranslationContext translationContext = context.getTranslationContextOfAppModel(modelId); + if (translationContext==null) { + log.trace("Topic Beacon: transmitSloViolatorInfo: No TranslationContext for app-model-id: {}", modelId); + return; + } + + // Get SLO metric decompositions (String) from TranslationContext + String sloMetricDecompositions = translationContext.getAdditionalResultsAs( + PredictionsPostTranslationPlugin.PREDICTION_SLO_METRIC_DECOMPOSITION, String.class); + log.debug("Topic Beacon: transmitSloViolatorInfo: SLO metric decompositions: {}", sloMetricDecompositions); + + if (StringUtils.isBlank(sloMetricDecompositions)) { + log.debug("Topic Beacon: transmitSloViolatorInfo: Payload is empty. Not sending event"); + return; + } + + // Send event with payload + log.debug("Topic Beacon: Transmitting SLO Violator info: event={}, topics={}", sloMetricDecompositions, properties.getSloViolationDetectorTopics()); + try { + context.sendMessageToTopics(sloMetricDecompositions, properties.getSloViolationDetectorTopics()); + } catch (JMSException e) { + log.error("Topic Beacon: EXCEPTION while transmitting SLO Violator info: event={}, topics={}, exception: ", + sloMetricDecompositions, properties.getSloViolationDetectorTopics(), e); + } + } +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionsPostTranslationPlugin.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionsPostTranslationPlugin.java new file mode 100644 index 0000000..a981510 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/plugins/PredictionsPostTranslationPlugin.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.plugins; + +import eu.nebulous.ems.translate.NebulousEmsTranslator; +import gr.iccs.imu.ems.control.plugin.PostTranslationPlugin; +import gr.iccs.imu.ems.control.properties.TopicBeaconProperties; +import gr.iccs.imu.ems.control.util.TopicBeacon; +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.dag.DAGNode; +import gr.iccs.imu.ems.translate.model.*; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import jakarta.annotation.PostConstruct; +import java.time.temporal.ValueRange; +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class PredictionsPostTranslationPlugin implements PostTranslationPlugin { + public final static String PREDICTION_SLO_METRIC_DECOMPOSITION = "NEBULOUS_PREDICTION_SLO_METRIC_DECOMPOSITION"; + public final static String PREDICTION_TOP_LEVEL_NODES_METRICS = "NEBULOUS_PREDICTION_TOP_LEVEL_NODES_METRICS"; + + @PostConstruct + public void created() { + log.debug("PredictionsPostTranslationPlugin: CREATED"); + } + + @Override + public void processTranslationResults(TranslationContext translationContext, TopicBeacon topicBeacon) { + log.debug("PredictionsPostTranslationPlugin.processTranslationResults(): BEGIN"); + + String sloMetricDecompositions = getSLOMetricDecompositionPayload(translationContext, topicBeacon); + translationContext.getAdditionalResults().put(PREDICTION_SLO_METRIC_DECOMPOSITION, sloMetricDecompositions); + log.debug("PredictionsPostTranslationPlugin.processTranslationResults(): SLO metrics decompositions: model={}, decompositions={}", + translationContext.getModelName(), sloMetricDecompositions); + + String metricsOfTopLevelNodes = getMetricsForPredictionPayload(translationContext, topicBeacon); + translationContext.getAdditionalResults().put(PREDICTION_TOP_LEVEL_NODES_METRICS, metricsOfTopLevelNodes); + log.debug("PredictionsPostTranslationPlugin.processTranslationResults(): Metrics of Top-Level nodes of model: model={}, metrics={}", + translationContext.getModelName(), metricsOfTopLevelNodes); + + log.debug("PredictionsPostTranslationPlugin.processTranslationResults(): END"); + } + + // ------------------------------------------------------------------------ + + /*public Set getGlobalGroupingMetrics(TranslationContext translationContext) { + // get all top-level nodes their component metrics + final Set nodes = new HashSet<>(); + final Deque q = new ArrayDeque<>(translationContext.getDAG().getTopLevelNodes()); + while (!q.isEmpty()) { + DAGNode node = q.pop(); + if (node.getGrouping()==Grouping.GLOBAL) { + nodes.add(node); + q.addAll(translationContext.getDAG().getNodeChildren(node)); + } + } + + // return metric names + return nodes.stream() + .map(DAGNode::getElementName) + .collect(Collectors.toSet()); + }*/ + + public String getSLOMetricDecompositionPayload(TranslationContext translationContext, TopicBeacon topicBeacon) { + List slos = _getSLOMetricDecomposition(translationContext); + if (slos.isEmpty()) { + return null; + } + + HashMap result = new HashMap<>(); + result.put("name", "_" + translationContext.getModelName()); + result.put("operator", "OR"); + result.put("constraints", slos); + result.put("version", topicBeacon.getModelVersion()); + + return topicBeacon.toJson(result); + } + + private @NonNull List _getSLOMetricDecomposition(TranslationContext translationContext) { + // Get metric and logical constraints + Map mcMap = translationContext.getMetricConstraints().stream() + .collect(Collectors.toMap(MetricConstraint::getName, mc -> mc)); + Map lcMap = translationContext.getLogicalConstraints().stream() + .collect(Collectors.toMap(LogicalConstraint::getName, lc -> lc)); + Map itcMap = translationContext.getIfThenConstraints().stream() + .collect(Collectors.toMap(IfThenConstraint::getName, ic -> ic)); + + // Create map of top-level element names and instances + Set topLevelNodes = translationContext.getDAG().getTopLevelNodes(); + Map topLevelNodesMap = topLevelNodes.stream() + .collect(Collectors.toMap(DAGNode::getElementName, x -> x)); + + // process each SLO + List sloMetricDecompositions = new ArrayList<>(); + for (String sloName : translationContext.getSLO()) { + DAGNode node = topLevelNodesMap.get(sloName); + if (node.getElement() instanceof ServiceLevelObjective slo) { + // get SLO constraint + Constraint sloConstraint = slo.getConstraint(); + // SLO must contain exactly one constraint + if (sloConstraint!=null) { + // decompose constraint + Object decomposition = _decomposeConstraint(sloConstraint, mcMap, lcMap, itcMap); + // cache decomposition + sloMetricDecompositions.add(decomposition); + } + } + } + + return sloMetricDecompositions; + } + + private Object _decomposeConstraint(Constraint constraintNode, Map mcMap, + Map lcMap, Map itcMap) + { + String elementName = constraintNode.getName(); + String elementClassName = constraintNode.getClass().getName(); + if (constraintNode instanceof MetricConstraint) { + MetricConstraint mc = mcMap.get(elementName); + return Map.of( + "name", NebulousEmsTranslator.nameNormalization.apply(mc.getName()), + "comparisonOperator", mc.getComparisonOperator(), + "threshold", mc.getThreshold()); + } else + if (constraintNode instanceof LogicalConstraint) { + LogicalConstraint lc = lcMap.get(elementName); + + // decompose child constraints + List list = new ArrayList<>(); + for (Constraint node : lc.getConstraints()) { + Object o = _decomposeConstraint(node, mcMap, lcMap, itcMap); + if (o!=null) list.add(o); + } + + // create decomposition result + Map result = new HashMap<>(); + result.put("name", NebulousEmsTranslator.nameNormalization.apply( lc.getName() )); + result.put("operator", lc.getLogicalOperator()); + result.put("constraints", list); + return result; + } else + if (constraintNode instanceof IfThenConstraint) { + IfThenConstraint itc = itcMap.get(elementName); + + // decompose child constraints + Object itcIf = _decomposeConstraint(itc.getIfConstraint(), mcMap, lcMap, itcMap); + Object itcThen = _decomposeConstraint(itc.getThenConstraint(), mcMap, lcMap, itcMap); + Object itcElse = _decomposeConstraint(itc.getElseConstraint(), mcMap, lcMap, itcMap); + + // create decomposition result + Map result = new HashMap<>(); + result.put("name", NebulousEmsTranslator.nameNormalization.apply( itc.getName() )); + result.put("if", itcIf); + result.put("then", itcThen); + result.put("else", itcElse); + return result; + } else + log.warn("_decomposeConstraint: Unsupported Constraint type: {} {}", elementName, elementClassName); + return null; + } + + // ------------------------------------------------------------------------ + + private String getMetricsForPredictionPayload(@NonNull TranslationContext _TC, TopicBeacon topicBeacon) { + HashSet metricsOfTopLevelNodes = getMetricsForPrediction(_TC); + if (metricsOfTopLevelNodes.isEmpty()) { + return null; + } + + // Convert to Translator-to-Forecasting Methods event format + final long currVersion = topicBeacon.getModelVersion(); + final TopicBeaconProperties properties = topicBeacon.getProperties(); + final ValueRange allowedPredictionRateRange = + ValueRange.of(properties.getPredictionMinAllowedRate(), properties.getPredictionMaxAllowedRate()); + List> payload = metricsOfTopLevelNodes.stream().map(mc -> { + HashMap map = new HashMap<>(); + map.put("metric", NebulousEmsTranslator.nameNormalization.apply( mc.getName() )); + map.put("component", mc.getComponentName()); + map.put("level", 3); + map.put("version", currVersion); + map.put("publish_rate", + mc.getSchedule()!=null && allowedPredictionRateRange.isValidValue(mc.getSchedule().getIntervalInMillis()) + ? mc.getSchedule().getIntervalInMillis() + : properties.getPredictionRate()); + return map; + }).collect(Collectors.toList()); + log.debug("Topic Beacon: Transmitting Prediction info: Metric Contexts in event format: {}", payload); + + // Skip event sending if payload is empty + if (payload.isEmpty()) { + return null; + } + + // Serialize payload + return topicBeacon.toJson(payload); + } + + private @NonNull HashSet getMetricsForPrediction(@NonNull TranslationContext _TC) { + // Process DAG top-level nodes + if (_TC.getDAG()==null) + throw new IllegalStateException("PredictionsPostTranslationPlugin: TranslationContext with 'null' DAG passed"); + Set topLevelNodes = _TC.getDAG().getTopLevelNodes(); + HashSet tcMetricsOfTopLevelNodes = new HashSet<>(); + + final Deque q = topLevelNodes.stream() + .filter(x -> + x.getElement() instanceof ServiceLevelObjective || + x.getElement() instanceof Metric) + .distinct() + .collect(Collectors.toCollection(ArrayDeque::new)); + + while (!q.isEmpty()) { + DAGNode node = q.pop(); + if (node.getElement() instanceof MetricContext) { + MetricContext metricContext = (node.getElement() instanceof MetricContext mc) ? mc : null; + tcMetricsOfTopLevelNodes.add(metricContext); + } else { + Set children = _TC.getDAG().getNodeChildren(node); + if (children!=null) q.addAll(children); + } + } + return tcMetricsOfTopLevelNodes; + } +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/ModelException.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/ModelException.java new file mode 100644 index 0000000..5021e34 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/ModelException.java @@ -0,0 +1,15 @@ +package eu.nebulous.ems.translate; + +public class ModelException extends Exception { + public ModelException(String message) { + super(message); + } + + public ModelException(String message, Throwable cause) { + super(message, cause); + } + + public ModelException(Throwable cause) { + super(cause); + } +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslationException.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslationException.java new file mode 100644 index 0000000..8be005f --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslationException.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate; + +public class NebulousEmsTranslationException extends RuntimeException { + public NebulousEmsTranslationException(String message) { + super(message); + } + + public NebulousEmsTranslationException(Throwable th) { + super(th); + } + + public NebulousEmsTranslationException(String message, Throwable th) { + super(message, th); + } +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslator.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslator.java new file mode 100644 index 0000000..3ae0450 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslator.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate; + +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.Translator; +import eu.nebulous.ems.translate.analyze.MetricModelAnalyzer; +import eu.nebulous.ems.translate.analyze.MetricModelValidator; +import eu.nebulous.ems.translate.analyze.ShorthandsExpansionHelper; +import eu.nebulous.ems.translate.generate.RuleGenerator; +import eu.nebulous.ems.translate.transform.GraphTransformer; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; +import org.yaml.snakeyaml.Yaml; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.function.Function; + +@Slf4j +@Service +@RequiredArgsConstructor +public class NebulousEmsTranslator implements Translator, InitializingBean { + + private final NebulousEmsTranslatorProperties properties; + private final ShorthandsExpansionHelper shorthandsExpansionHelper; + private final MetricModelValidator validator; + private final MetricModelAnalyzer analyzer; + private final GraphTransformer transformer; + private final RuleGenerator generator; + + public final static Function nameNormalization = + (name) -> name.replace("_", "__").replaceAll("[^A-Za-z0-9_]", "_"); + public final static Function nameToTopic = nameNormalization; + + @Override + public void afterPropertiesSet() throws Exception { + log.info("NebulousEmsTranslator: initialized"); + } + + // ================================================================================================================ + // Public API + + @Override + public TranslationContext translate(String metricModelPath) { + if (StringUtils.isBlank(metricModelPath)) { + log.error("NebulousEmsTranslator: No metric model specified"); + throw new NebulousEmsTranslationException("No metric model specified"); + } + + log.info("NebulousEmsTranslator: Parsing metric model file: {}", metricModelPath); + Object modelObj; + try { + // -- Load model ------------------------------------------------------ + Path inputFile = Paths.get(properties.getModelsDir(), metricModelPath); + String yamlStr = Files.readString(inputFile); + + // Parsing YAML file with SnakeYAML, since Jackson Parser does not support Anchors and references + Yaml yaml = new Yaml(); + modelObj = yaml.loadAs(yamlStr, Object.class); + log.trace("NebulousEmsTranslator: YAML model contents:\n{}", modelObj); + + // -- Translate model --------------------------------------------- + log.info("NebulousEmsTranslator: Translating metric model: {}", metricModelPath); + TranslationContext _TC = translate(modelObj, metricModelPath); + log.info("NebulousEmsTranslator: Translating metric model completed: {}", metricModelPath); + + return _TC; + } catch (Exception e) { + log.error("NebulousEmsTranslator: EXCEPTION while translating metric model file: {}\nException: ", e.getMessage(), e); + throw new NebulousEmsTranslationException("Error while translating metric model file: "+metricModelPath, e); + } + } + + // ================================================================================================================ + // Private methods + + private TranslationContext translate(Object modelObj, String modelFileName) throws Exception { + log.debug("NebulousEmsTranslator.translate(): BEGIN: metric-model={}", modelObj); + + // Get model name + String modelName = getModelName(modelFileName); + + // Initialize data structures + TranslationContext _TC = new TranslationContext(modelName, modelFileName); + + // -- Expand shorthand expressions ------------------------------------ + log.debug("NebulousEmsTranslator.translate(): Expanding shorthand expressions: {}", modelName); + shorthandsExpansionHelper.expandShorthandExpressions(modelObj, modelName); + + // -- Schematron Validation ------------------------------------------- + log.debug("NebulousEmsTranslator.translate(): Validating metric model: {}", modelName); + if (!properties.isSkipModelValidation()) { + validator.validateModel(modelObj, modelName); + log.debug("MetricModelAnalyzer.analyzeModel(): Metric model is valid: {}", modelName); + } + + // -- Analyze metric model -------------------------------------------- + log.debug("NebulousEmsTranslator.translate(): Analyzing model..."); + analyzer.analyzeModel(_TC, modelObj, modelName); + log.debug("NebulousEmsTranslator.translate(): Analyzing model... done"); + + // -- Transform graph ------------------------------------------------- + //XXX:TODO: Not sure if it is needed in Nebulous (removes MVVs and adds TL metrics above TL metric contexts, + //XXX:TODO: ... but MVVs are not used, neither metrics (only metric contexts)). + log.debug("NebulousEmsTranslator.translate(): Transforming DAG..."); + transformer.transformGraph(_TC.getDAG()); + log.debug("NebulousEmsTranslator.translate(): Transforming DAG... done"); + + // -- Generate EPL rules ---------------------------------------------- + log.debug("NebulousEmsTranslator.translate(): Generating EPL rules..."); + generator.generateRules(_TC); + log.debug("NebulousEmsTranslator.translate(): Generating EPL rules... done"); + + log.debug("NebulousEmsTranslator.translate(): END: metric-model={}", modelObj); + log.trace("NebulousEmsTranslator.translate(): END: result={}", _TC); + return _TC; + } + + private String getModelName(String modelFileName) { + String modelName = Paths.get(modelFileName).toFile().getName(); + modelName = StringUtils.removeEndIgnoreCase(modelName, ".yaml"); + modelName = StringUtils.removeEndIgnoreCase(modelName, ".yml"); + return modelName; + } + +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslatorProperties.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslatorProperties.java new file mode 100644 index 0000000..c232c80 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/NebulousEmsTranslatorProperties.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate; + +import gr.iccs.imu.ems.translate.Grouping; +import gr.iccs.imu.ems.util.EmsConstant; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +@Slf4j +@Data +@Validated +@Configuration +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "translator") +public class NebulousEmsTranslatorProperties implements InitializingBean { + @Override + public void afterPropertiesSet() { + log.debug("NebulousEmsTranslatorProperties: {}", this); + } + + // Model validation settings + private boolean skipModelValidation; + + // Translator parameters + private String modelsDir = "/models"; + + // Sensor processing parameters + private long sensorMinInterval; + private long sensorDefaultInterval; + + // TC processing settings + private Grouping leafNodeGrouping = Grouping.PER_INSTANCE; + private boolean pruneMvv = true; + private boolean addTopLevelMetrics = true; + private String fullNamePattern = "{ELEM}"; + + // Busy-Status metric settings + private String busyStatusDestinationNameFormatter = "busy.%s"; + + // Orphan metrics + private boolean includeOrphanMetrics = true; + private String orphanMetricsParentName = "_ORPHANED_METRICS_ROOT_VAR_"; + + // DAG post-processing + private boolean updateNodesWithRequiringComponents = true; + private boolean useCommonOrphansParent; +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/TranslatorApplication.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/TranslatorApplication.java new file mode 100644 index 0000000..433396b --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/TranslatorApplication.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate; + +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.TranslationContextPrinter; +import gr.iccs.imu.ems.translate.TranslationContextPrinterProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import java.nio.file.Paths; + +/* + * Run the 'TranslatorApplication' from command line + * + * 1) Compile application and retrieve dependencies: + * mvn clean package + * mvn dependency:copy-dependencies + * + * 2) Set environment variables: + * EMS_CONFIG_DIR=.... + * SPRING_CONFIG_LOCATION=classpath:rule-templates.yml,file:${EMS_CONFIG_DIR}/ems-server.yml + * + * 3) Run the application: + * Windows: + * java -cp target\classes;target\dependency\* eu.nebulous.ems.translate.TranslatorApplication ...<>... + * Linux: + * java -cp target/classes:target/dependency/* eu.nebulous.ems.translate.TranslatorApplication ...<>... + */ +@Slf4j +@SpringBootApplication +@RequiredArgsConstructor +public class TranslatorApplication implements CommandLineRunner { + + private static boolean standalone = false; + private final NebulousEmsTranslator translator; + private final NebulousEmsTranslatorProperties translatorProperties; + private final TranslationContextPrinter printer; + private final TranslationContextPrinterProperties printerProperties; + + public static void main(String[] args) { + standalone = true; + SpringApplication.run(TranslatorApplication.class, args); + } + + @Override + public void run(String... args) { + if (!standalone) return; // Execute only if called by 'main()' + + log.info("Testing MODEL-to-EPL Translator"); + log.info("Base dir: {}", Paths.get("").toFile().getAbsolutePath()); + + log.info("Args: {}", java.util.Arrays.asList(args)); + String modelPath = (args.length > 0 && !args[0].trim().isEmpty()) + ? args[0].trim() : "ems-main/surveillance_app_SAMPLE_metric_model.yml"; + + log.info("App-model: {}", modelPath); + translatorProperties.setModelsDir(""); + TranslationContext _TC = translator.translate(modelPath); + //log.info("TC: {}", _TC); + + printerProperties.getDag().setExportToFileEnabled(true); + printerProperties.getDag().setExportFormats(new String[] { "svg" }); + printerProperties.getDag().setExportImageWidth(1600); + printerProperties.getDag().setExportPath("."); + printer.printResults(_TC, modelPath+"-export"); + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AbstractHelper.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AbstractHelper.java new file mode 100644 index 0000000..1b0a392 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AbstractHelper.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import gr.iccs.imu.ems.translate.TranslationContext; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +abstract class AbstractHelper { + protected MetricModelAnalyzer.AdditionalTranslationContextData $$(TranslationContext _TC) { + return _TC.$(MetricModelAnalyzer.AdditionalTranslationContextData.class); + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AnalysisUtils.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AnalysisUtils.java new file mode 100644 index 0000000..b324ee3 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/AnalysisUtils.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import eu.nebulous.ems.translate.ModelException; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Map; + +@Slf4j +@Service +@RequiredArgsConstructor +public class AnalysisUtils { + final static String CONTAINER_NAME_KEY = "_containerName"; + + final static List COMPARISON_OPERATORS = + List.of("<", "<=", "=<", ">", ">=", "=<", "=", "<>", "!="); + final static List LOGICAL_OPERATORS = + List.of("and", "or"); + + // ------------------------------------------------------------------------ + // Exceptions and Casting method + // ------------------------------------------------------------------------ + + static RuntimeException createException(String s) { + log.error("Parse error: {}", s); + return new RuntimeException(new ModelException(s)); + } + + static RuntimeException createException(String s, Throwable t) { + log.error("Parse error: {}: ", s, t); + return new RuntimeException(s, t); + } + + static List asList(Object o) { + if (o==null) return null; + if (o instanceof List l) return l; + log.error("AnalysisUtils.asList: input: {}", o); + throw createException("Object is not a List: "+o); + } + + static Map asMap(Object o) { + if (o==null) return null; + if (o instanceof Map m) return m; + log.error("AnalysisUtils.asMap: input: {}", o); + throw createException("Object is not a Map: "+o); + } + + // ------------------------------------------------------------------------ + // Name and Field methods + // ------------------------------------------------------------------------ + + static NamesKey createNamesKey(@NonNull NamesKey parentNamesKey, @NonNull String name) { + return (NamesKey.isFullName(name)) + ? NamesKey.create(name) : NamesKey.create(parentNamesKey.parent, name); + } + + static NamesKey getNamesKey(@NonNull Object spec, @NonNull String name) { + return NamesKey.create(getContainerName(spec), name); + } + + static String getContainerName(@NonNull Object spec) { + return getSpecField(spec, CONTAINER_NAME_KEY); + } + + static String getSpecField(Object o, String field) { + return getSpecField(o, field, "Block '%s' is not String: "); + } + + static String getSpecField(Object o, String field, String exceptionMessage) { + try { + Map spec = asMap(o); + Object oValue = spec.get(field); + if (oValue == null) + return null; + if (oValue instanceof String s) { + s = s.trim(); + return s; + } + throw createException(exceptionMessage.formatted(field) + spec); + } catch (Exception e) { + throw createException(exceptionMessage.formatted(field) + o, e); + } + } + + static String getMandatorySpecField(Object o, String field, String exceptionMessage) { + String val = getSpecField(o, field, exceptionMessage); + if (val==null) + throw createException(exceptionMessage.formatted(field) + o); + return val; + } + + static String getSpecName(Object o) { + return getSpecField(o, "name"); + } + + static Double getSpecNumber(Object o, String field) { + try { + Map spec = asMap(o); + Object oValue = spec.get(field); + if (oValue == null) return null; + if (oValue instanceof Number n) { + return n.doubleValue(); + } + if (oValue instanceof String s) { + return Double.parseDouble(s); + } + throw createException("Block '"+field+"' is not Number: " + spec); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + static Double getSpecNumber(Object o, String field, String exceptionMessage) { + Double val = getSpecNumber(o, field); + if (val==null) + throw createException(exceptionMessage+o); + return val; + } + + static Boolean getSpecBoolean(Object o, String field) { + try { + Map spec = asMap(o); + Object oValue = spec.get(field); + if (oValue == null) return null; + if (oValue instanceof Boolean b) { + return b; + } + if (oValue instanceof String s) { + return getBooleanValue(s, false); + } + throw createException("Block '"+field+"' is not Boolean: " + spec); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + static Boolean getSpecBoolean(Object o, String field, boolean defaultValue) { + Boolean val = getSpecBoolean(o, field); + return val!=null ? val : defaultValue; + } + + static Boolean getSpecBoolean(Object o, String field, String exceptionMessage) { + Boolean val = getSpecBoolean(o, field); + if (val==null) + throw createException(exceptionMessage+o); + return val; + } + + static boolean getBooleanValue(String val, boolean defaultValue) { + if (StringUtils.isBlank(val)) return defaultValue; + return "true".equalsIgnoreCase(val.trim()); + } + + // ------------------------------------------------------------------------ + // Unit normalization methods + // ------------------------------------------------------------------------ + + static ChronoUnit normalizeTimeUnit(String s) { + s = s.trim().toLowerCase(); + return switch (s) { + case "ms", "msec", "millisecond", "milliseconds" -> ChronoUnit.MILLIS; + case "s", "sec", "second", "seconds" -> ChronoUnit.SECONDS; + case "m", "min", "minute", "minutes" -> ChronoUnit.MINUTES; + case "h", "hr", "hrs", "hour", "hours" -> ChronoUnit.HOURS; + case "d", "day", "days" -> ChronoUnit.DAYS; + case "w", "week", "weeks" -> ChronoUnit.WEEKS; + case "mon", "month", "months" -> ChronoUnit.MONTHS; + case "yr", "year", "years" -> ChronoUnit.YEARS; + default -> throw createException("Not supported time unit: "+s); + }; + } + + // ------------------------------------------------------------------------ + // Query methods + // ------------------------------------------------------------------------ + + static boolean isDouble(String s) { + try { + Double.parseDouble(s); + } catch (Exception e) { + return false; + } + return true; + } + + static boolean isDoubleOrInfinity(String s) { + s = s.trim(); + if (StringUtils.equalsAnyIgnoreCase(s, "-inf", "+inf", "inf")) return true; + return isDouble(s); + } + + static double getDoubleValue(String s) { + s = s.trim(); + return switch (s.toLowerCase()) { + case "-inf" -> Double.NEGATIVE_INFINITY; + case "+inf", "inf" -> Double.POSITIVE_INFINITY; + default -> Double.parseDouble(s); + }; + } + + static boolean isComparisonOperator(String s) { + return COMPARISON_OPERATORS.contains(s); + } + + static boolean isLogicalOperator(String s) { + return LOGICAL_OPERATORS.contains(s); + } + +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ConstraintsHelper.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ConstraintsHelper.java new file mode 100644 index 0000000..18f9f05 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ConstraintsHelper.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.model.*; +import eu.nebulous.ems.translate.NebulousEmsTranslatorProperties; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.*; + +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.*; + +// ------------------------------------------------------------------------ +// Constraints decomposition methods +// ------------------------------------------------------------------------ + +@Slf4j +@Service +@RequiredArgsConstructor +class ConstraintsHelper extends AbstractHelper { + private final static String DEFAULT_CONSTRAINT_NAME_SUFFIX = "_CONSTRAINT"; + + private final NebulousEmsTranslatorProperties properties; + private final MetricsHelper metricsHelper; + + void decomposeConstraints(TranslationContext _TC, Map sloList) { + sloList.forEach((sloNamesKey, sloSpec) -> { + ServiceLevelObjective slo = ServiceLevelObjective.builder() + .name(sloNamesKey.name()) + .object(sloSpec) + .build(); + _TC.addSLO(slo); + _TC.getDAG().addTopLevelNode(slo); + + Object object = asMap(sloSpec).get("constraint"); + if (object==null) + throw createException("SLO without 'constraint': "+sloSpec); + if (object instanceof Map constraintSpec) { + Constraint constraint = decomposeConstraint(_TC, asMap(constraintSpec), sloNamesKey, slo); + slo.setConstraint(constraint); + } else + throw createException("SLO constraint is not Map: "+sloSpec); + }); + } + + Constraint decomposeConstraint(@NonNull TranslationContext _TC, Map constraintSpec, NamesKey parentNamesKey, NamedElement parent) { + // Get constraint type + String type = getSpecField(constraintSpec, "type"); + if (StringUtils.isBlank(type)) + throw createException("Constraint without 'type': "+constraintSpec); + + String constraintName = getSpecName(constraintSpec); + if (StringUtils.isBlank(constraintName)) + constraintName = parentNamesKey.child + DEFAULT_CONSTRAINT_NAME_SUFFIX; + NamesKey constraintNamesKey = createNamesKey(parentNamesKey, constraintName); + if ($$(_TC).constraintsUsed.containsKey(constraintNamesKey)) { + Constraint cachedConstraint = $$(_TC).constraintsUsed.get(constraintNamesKey); + _TC.getDAG().addNode(parent, cachedConstraint); + return cachedConstraint; + } + + // Delegate constraint decomposition based on type + Constraint constraintNode = switch (type) { + case "metric" -> + decomposeMetricConstraint(_TC, constraintSpec, parentNamesKey, parent); + case "logical" -> + decomposeLogicalConstraint(_TC, constraintSpec, parentNamesKey, parent); + case "conditional" -> + decomposeConditionalConstraint(_TC, constraintSpec, parentNamesKey, parent); + default -> + throw createException("Constraint 'type' not supported: " + constraintSpec); + }; + $$(_TC).constraintsUsed.put(constraintNamesKey, constraintNode); + + return constraintNode; + } + + private MetricConstraint decomposeMetricConstraint(@NonNull TranslationContext _TC, Map constraintSpec, NamesKey parentNamesKey, NamedElement parent) { + // Get needed fields + String constraintName = getSpecName(constraintSpec); + String metricName = getMandatorySpecField(constraintSpec, "metric", "Metric Constraint without 'metric': "); + String comparisonOperator = getMandatorySpecField(constraintSpec, "operator", "Metric Constraint without 'operator': "); + Double threshold = getSpecNumber(constraintSpec, "threshold", "Metric Constraint without 'threshold': "); + + if (StringUtils.isBlank(constraintName)) + constraintName = parentNamesKey.child + DEFAULT_CONSTRAINT_NAME_SUFFIX; + NamesKey constraintNamesKey = createNamesKey(parentNamesKey, constraintName); + NamesKey metricNamesKey = createNamesKey(parentNamesKey, metricName); + + // Further field checks + if (! $$(_TC).allMetrics.containsKey(metricNamesKey)) + throw createException("Unspecified metric '"+metricNamesKey.name()+"' found in metric constraint: "+ constraintSpec); + + if (! isComparisonOperator(comparisonOperator)) + throw createException("Unknown comparison operator '"+comparisonOperator+"' in metric constraint: "+ constraintSpec); + + // Update TC + MetricConstraint metricConstraint = MetricConstraint.builder() + .name(constraintNamesKey.name()) + .object(constraintSpec) + .comparisonOperator(ComparisonOperatorType.byOperator(comparisonOperator)) + .threshold(threshold) + .build(); + _TC.getDAG().addNode(parent, metricConstraint); + + // Decompose metric + MetricContext metric = metricsHelper.decomposeMetric( + _TC, asMap($$(_TC).allMetrics.get(metricNamesKey)), constraintNamesKey, metricConstraint); + + // Complete TC update + metricConstraint.setMetricContext(metric); + _TC.addMetricConstraint(metricConstraint); + + return metricConstraint; + } + + private LogicalConstraint decomposeLogicalConstraint(TranslationContext _TC, Map constraintSpec, NamesKey parentNamesKey, NamedElement parent) { + // Get needed fields + String constraintName = getSpecName(constraintSpec); + String logicalOperator = getMandatorySpecField(constraintSpec, "operator", "Logical Constraint without 'operator': "); + List composingConstraints = asList(constraintSpec.get("constraints")); + + if (StringUtils.isBlank(constraintName)) + constraintName = parentNamesKey.child + DEFAULT_CONSTRAINT_NAME_SUFFIX; + NamesKey constraintNamesKey = createNamesKey(parentNamesKey, constraintName); + + // Further field checks + if (! isLogicalOperator(logicalOperator)) + throw createException("Unknown logical operator '"+logicalOperator+"' in metric constraint: "+ constraintSpec); + if (composingConstraints==null || composingConstraints.isEmpty()) + throw createException("At least one composing constraint must be provided in logical constraint: "+ constraintSpec); + + // Update TC + LogicalConstraint logicalConstraint = LogicalConstraint.builder() + .name(constraintNamesKey.name()) + .object(constraintSpec) + .logicalOperator(LogicalOperatorType.valueOf(logicalOperator.trim().toUpperCase())) + .build(); + _TC.getDAG().addNode(parent, logicalConstraint); + + // Decompose composing constraints + List composingConstraintsList = new ArrayList<>(); + for (Object cc : composingConstraints) { + String sloName = cc.toString(); + Constraint childConstraint = decomposeComposingConstraint(_TC, sloName, parentNamesKey, logicalConstraint); + composingConstraintsList.add(childConstraint); + } + logicalConstraint.setConstraints(composingConstraintsList); + + // Complete TC update + _TC.addLogicalConstraint(logicalConstraint); + + return logicalConstraint; + } + + private IfThenConstraint decomposeConditionalConstraint(TranslationContext _TC, Map constraintSpec, NamesKey parentNamesKey, NamedElement parent) { + // Get needed fields + String constraintName = getSpecName(constraintSpec); + + if (StringUtils.isBlank(constraintName)) + constraintName = parentNamesKey.child + DEFAULT_CONSTRAINT_NAME_SUFFIX; + NamesKey constraintNamesKey = createNamesKey(parentNamesKey, constraintName); + + // Get the referenced constraints names (their SLOs' actually) + String ifSloName = getMandatorySpecField(constraintSpec, "if", "Unspecified IF part in conditional constraint '"+constraintNamesKey.name()+"': "+ constraintSpec); + String thenSloName = getMandatorySpecField(constraintSpec, "then", "Unspecified THEN part in conditional constraint '"+constraintNamesKey.name()+"': "+ constraintSpec); + String elseSloName = getSpecField(constraintSpec, "else"); + + // Update TC + IfThenConstraint conditionalConstraint = IfThenConstraint.builder() + .name(constraintNamesKey.name()) + .object(constraintSpec) + .build(); + _TC.getDAG().addNode(parent, conditionalConstraint); + + // Decompose the composing metrics + Constraint ifConstraint = decomposeComposingConstraint(_TC, ifSloName, parentNamesKey, conditionalConstraint); + Constraint thenConstraint = decomposeComposingConstraint(_TC, thenSloName, parentNamesKey, conditionalConstraint); + Constraint elseConstraint = StringUtils.isNotBlank(elseSloName) + ? decomposeComposingConstraint(_TC, elseSloName, parentNamesKey, conditionalConstraint) : null; + + // Update the conditional (main) constraint + conditionalConstraint.setIfConstraint(ifConstraint); + conditionalConstraint.setThenConstraint(thenConstraint); + if (elseConstraint!=null) + conditionalConstraint.setElseConstraint(elseConstraint); + + // Complete TC update + _TC.addIfThenConstraint(conditionalConstraint); + + return conditionalConstraint; + } + + private Constraint decomposeComposingConstraint(TranslationContext _TC, String sloName, NamesKey parentNamesKey, Constraint parentConstraint) { + // Get referenced constraint spec (its SLO spec actually) + Object sloSpec = $$(_TC).allSLOs.get(NamesKey.create(parentNamesKey.parent, sloName)); + + // Construct SLO namesKey + NamesKey sloNamesKey = NamesKey.create(getContainerName(sloSpec), sloName); + + // Get constraint spec from SLO spec + Map constraintSpec = asMap(asMap(sloSpec).get("constraint")); + + // Decompose composing constraint + return decomposeConstraint(_TC, constraintSpec, sloNamesKey, parentConstraint); + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/FunctionsHelper.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/FunctionsHelper.java new file mode 100644 index 0000000..00347cd --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/FunctionsHelper.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import gr.iccs.imu.ems.brokercep.cep.MathUtil; +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.util.FunctionDefinition; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.*; + +// ------------------------------------------------------------------------ +// Custom Function processing methods +// ------------------------------------------------------------------------ + +@Slf4j +@Service +@RequiredArgsConstructor +class FunctionsHelper extends AbstractHelper { + void processFunction(TranslationContext _TC, Object s) { + // Get function definition elements + String name = getSpecName(s); + String expression = getMandatorySpecField(s, "expression", "Custom Function without expression: "); + List args = asList(((Map) s).get("arguments")); + + // Check function definition elements + if (StringUtils.isBlank(name)) throw createException("Custom Function with blank name: "+ s); + if (StringUtils.isBlank(expression)) throw createException("Custom Function with blank expression: "+ s); + if (args==null || args.isEmpty()) + throw createException("Custom Function without arguments: "+ s); + if (args.stream().anyMatch(a -> !(a instanceof String))) + throw createException("Custom Function spec contains non-string arguments: "+ s); + + // Check if function name is unique + if (_TC.containsFunction(name) || $$(_TC).functionNames.contains(name)) + throw createException("Custom Function with 'name' already exists: "+ s); + + // Check if function definition is correct/valid + List argsList = args.stream().map(Object::toString).toList(); + FunctionDefinition fd = new FunctionDefinition() + .setName(name).setExpression(expression).setArguments(argsList); + MathUtil.addFunctionDefinition(fd); + MathUtil.clearFunctionDefinitions(); + + // Update TC + _TC.addFunction(gr.iccs.imu.ems.translate.model.Function.builder() + .name(name) + .expression(expression) + .arguments(argsList) + .build()); + log.debug("Added custom function: {}", name); + + $$(_TC).functionNames.add(name); + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelAnalyzer.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelAnalyzer.java new file mode 100644 index 0000000..f9f21ce --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelAnalyzer.java @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.ParseContext; +import eu.nebulous.ems.translate.NebulousEmsTranslatorProperties; +import gr.iccs.imu.ems.translate.Grouping; +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.dag.DAGNode; +import gr.iccs.imu.ems.translate.model.*; +import lombok.Data; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.*; + +@Slf4j +@Service +@RequiredArgsConstructor +public class MetricModelAnalyzer { + private final NebulousEmsTranslatorProperties properties; + private final FunctionsHelper functionsHelper; + private final ConstraintsHelper constraintsHelper; + private final MetricsHelper metricsHelper; + private final NodeUpdatingHelper nodeUpdatingHelper; + + // ================================================================================================================ + // Model analysis methods + + public void analyzeModel(@NonNull TranslationContext _TC, @NonNull Object metricModel, String modelName) throws Exception { + log.debug("MetricModelAnalyzer.analyzeModel(): BEGIN: metric-model: {}", metricModel); + + // ----- Initialize jsonpath context ---------------------------------- + Configuration jsonpathConfig = Configuration.defaultConfiguration(); + ParseContext parseContext = JsonPath.using(jsonpathConfig); + DocumentContext ctx = parseContext.parse(metricModel); + + // ----- Model processing --------------------------------------------- + log.debug("MetricModelAnalyzer.analyzeModel(): Analyzing metric model: {}", metricModel); + Map topLevelModelElements = ctx.read("$", Map.class); + + // ----- Define additional translation structures and cache them in _TC ----- + _TC.setExtensionContext(new AdditionalTranslationContextData()); + + // set full-name pattern in _TC, for full-name generation + if (StringUtils.isNotBlank(properties.getFullNamePattern())) { + log.debug("MetricModelAnalyzer.analyzeModel(): Set full name pattern to: {}", properties.getFullNamePattern()); + _TC.setFullNamePattern(properties.getFullNamePattern()); + } + + // ----- Process function specifications ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Process function specs"); + if (topLevelModelElements.containsKey("functions")) { + List functionSpecsList = ctx.read("$.functions.*", List.class); + functionSpecsList.stream().filter(s -> s instanceof Map).forEach(s -> { + functionsHelper.processFunction(_TC, s); + }); + } + + // ----- Get component and scope names ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Check name uniqueness"); + List componentNamesList = ctx.read("$.spec.components.*.name", List.class); + List scopeNamesList = ctx.read("$.spec.scopes.*.name", List.class); + log.debug("Component names: {}", componentNamesList); + log.debug(" Scope names: {}", scopeNamesList); + + // Check name uniqueness + checkNameUniqueness(componentNamesList, scopeNamesList); + Set componentNames = new LinkedHashSet<>(componentNamesList); + Set scopeNames = new LinkedHashSet<>(scopeNamesList); + + // ----- Set container name and make mutable all 'spec' elements (and sub-elements) ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Set element containers"); + Map modelRoot = asMap(ctx.read("$")); + Object specNode = modelRoot.get("spec"); + specNode = addContainerNameAndMakeMutable(specNode, null); + modelRoot.put("spec", specNode); + + // ----- Create object contexts for components ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Create object contexts"); + createObjectContexts(_TC, componentNames); + + // ----- Build flat lists of metrics, constraints and SLOs, and check their specs ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Build element lists"); + buildElementLists(_TC, modelRoot); + log.debug(" All Metrics: {}", $$(_TC).allMetrics); + log.debug("All Constraints: {}", $$(_TC).allConstraints); + log.debug(" All SLOs: {}", $$(_TC).allSLOs); + + // ----- Build of constants lists ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Build constants list"); + buildConstantsList(_TC, modelRoot); + + // ----- Process SLOs ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Process SLOs"); + processSLOs(_TC); + + // ----- Process orphan metrics (i.e. not used in constraints) ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Process orphan metrics"); + metricsHelper.processOrphanMetrics(_TC); + + // ----- Infer groupings (levels) ----- + log.debug("MetricModelAnalyzer.analyzeModel(): Infer and set element groupings"); + inferGroupings(_TC); + + // ----- Build components to SLOs maps (including those in the scopes they participate) ----- + if (properties.isUpdateNodesWithRequiringComponents()) { + log.debug("MetricModelAnalyzer.analyzeModel(): Updating DAG nodes with requiring component names"); + + // Build component to SLO maps + nodeUpdatingHelper.buildComponentsToSLOsMap(_TC, ctx, componentNames); + nodeUpdatingHelper.buildSLOToComponentsMap(_TC); + + // Update DAG nodes with components requiring them (busy-status and orphans are required by all components) + nodeUpdatingHelper.updateDAGNodesWithComponents(_TC, componentNames); + } + + // ----- Remove Orphan metrics common parent variable ----- + if (! properties.isUseCommonOrphansParent()) { + log.debug("MetricModelAnalyzer.analyzeModel(): Removing common orphan metrics parent"); + nodeUpdatingHelper.removeCommonOrphanMetricsParent(_TC); + } + + // ---------------------------------------------------------- + + log.debug("MetricModelAnalyzer.analyzeModel(): END: metric-model: {}", metricModel); + } + + // ------------------------------------------------------------------------ + // Additional translation data structures and shorthand retrieval method + // ------------------------------------------------------------------------ + + private AdditionalTranslationContextData $$(TranslationContext _TC) { + return _TC.$(AdditionalTranslationContextData.class); + } + + @Data + @Accessors(fluent = true) + static class AdditionalTranslationContextData { + final Map parentSpecs = new LinkedHashMap<>(); // i.e. all component and scope specs + final Map objectContexts = new LinkedHashMap<>(); // i.e. object contexts for all components + final Map allSLOs = new LinkedHashMap<>(); + final Map allConstraints = new LinkedHashMap<>(); + final Map allMetrics = new LinkedHashMap<>(); + final Map metricsUsed = new LinkedHashMap<>(); + final Map constraintsUsed = new LinkedHashMap<>(); + final Map constants = new LinkedHashMap<>(); + final Set functionNames = new HashSet<>(); + Map> componentsToSLOsMap; + Map> slosToComponentsMap; + } + + // ------------------------------------------------------------------------ + // Analysis helper methods + // ------------------------------------------------------------------------ + + private static void checkNameUniqueness(List componentNamesList, List scopeNamesList) { + List all = new ArrayList<>(componentNamesList); + all.addAll(scopeNamesList); + log.trace(" ALL names: {}", all); + List duplicateNames = all.stream() + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) + .entrySet().stream() + .filter(e -> e.getValue() > 1) + .map(Map.Entry::getKey) + .toList(); + if (! duplicateNames.isEmpty()) { + log.error("Duplicate names: {}", duplicateNames); + throw createException("Naming conflicts exist for: "+duplicateNames); + } + } + + private Object addContainerNameAndMakeMutable(Object o, String parentName) { + if (o instanceof Map m) { + Map newM = new LinkedHashMap<>(); + newM.put(CONTAINER_NAME_KEY, parentName); + String myName0 = getSpecName(o); + String myName = parentName != null ? parentName : myName0; + m.forEach((k,v) -> newM.put(k.toString(), addContainerNameAndMakeMutable(v, myName))); + return newM; + } else + if (o instanceof List l) { + List newL = new LinkedList<>(); + l.forEach(v -> newL.add(addContainerNameAndMakeMutable(v, parentName))); + return newL; + } + return o; + } + + private void createObjectContexts(TranslationContext _TC, Set componentNames) { + Map objectContexts = componentNames.stream() + .collect(Collectors.toMap( + Function.identity(), + name -> ObjectContext.builder() + .component(Component.builder().name(name).build()) + .build() + )); + $$(_TC).objectContexts.putAll(objectContexts); + } + + private void buildElementLists(TranslationContext _TC, Map modelRoot) { + asList(JsonPath.read(modelRoot, "$.spec.*.*")).stream().filter(Objects::nonNull).forEach(spec -> { + log.debug("buildElementLists: {}", spec); + String parentName = getSpecName(spec); + if (StringUtils.isBlank(parentName)) throw createException("Component or Scope with no name: " + spec); + $$(_TC).parentSpecs.computeIfAbsent(parentName, (key)->spec); + + // Requirements (SLOs) flat list building + List slos = JsonPath.read(spec, + "$[?(@.requirements!=null && @.requirements.*[?(@.type=='slo')])].requirements.*"); + slos.stream().filter(Objects::nonNull).forEach(sloSpec -> { + log.debug("buildElementLists: SLO (requirements): {}", sloSpec); + String sloName = getSpecName(sloSpec); + if (StringUtils.isBlank(sloName)) throw createException("SLO spec with no name: " + sloSpec); + $$(_TC).allSLOs.put(NamesKey.create(parentName, sloName), sloSpec); + }); + + // Constraints flat list building + slos.stream().filter(Objects::nonNull).forEach(sloSpec -> { + log.debug("buildElementLists: SLO (constraints): {}", sloSpec); + String sloName = getSpecName(sloSpec); + if (StringUtils.isBlank(sloName)) throw createException("SLO spec with no name: " + sloSpec); + + NamesKey sloNamesKey = NamesKey.create(parentName, sloName); + Map constraintSpec = asMap(asMap(sloSpec).get("constraint")); + NamesKey constraintNamesKey = createNamesKey(sloNamesKey, sloName); + $$(_TC).allConstraints.put(constraintNamesKey, constraintSpec); + }); + + // Metrics flat list building + List metrics = JsonPath.read(spec, "$[?(@.metrics!=null)].metrics.*"); + metrics.stream().filter(Objects::nonNull).forEach(metricSpec -> { + log.debug("buildElementLists: Metric: {}", metricSpec); + String metricName = getSpecName(metricSpec); + if (StringUtils.isBlank(metricName)) throw createException("Metric spec with no name: " + metricSpec); + NamesKey namesKey = NamesKey.create(parentName, metricName); + $$(_TC).allMetrics.put(namesKey, metricSpec); + }); + }); + } + + private void buildConstantsList(TranslationContext _TC, Map modelRoot) { + asList(JsonPath.read(modelRoot, "$.spec.*.*.metrics.*[?(@.type=='constant')]")).stream().filter(Objects::nonNull).forEach(spec -> { + metricsHelper.processConstant(_TC, asMap(spec), getContainerName(spec)); + }); + } + + // ------------------------------------------------------------------------ + // Process SLOs -- This is the main decomposition method (uses helpers) + // ------------------------------------------------------------------------ + + private void processSLOs(TranslationContext _TC) { + // ----- Decompose SLOs with metric constraints to their metric hierarchies ----- + Map metricSLOs = $$(_TC).allSLOs.entrySet().stream() + //.peek(x -> log.warn("--------> {}", getSpecField(asMap(x.getValue()).get("constraint"), "type") )) + .filter(x -> "metric".equals( getSpecField(asMap(x.getValue()).get("constraint"), "type") )) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + constraintsHelper.decomposeConstraints(_TC, metricSLOs); + + // ----- Decompose SLOs with non-metric constraints ----- + Map nonMetricSLOs = new LinkedHashMap<>($$(_TC).allSLOs); + nonMetricSLOs.keySet().removeAll( metricSLOs.keySet() ); + constraintsHelper.decomposeConstraints(_TC, nonMetricSLOs); + } + + // ------------------------------------------------------------------------ + // Grouping inference methods + // ------------------------------------------------------------------------ + + private void inferGroupings(TranslationContext _TC) { + Grouping topLevelGrouping = Grouping.GLOBAL; + Grouping leafGrouping = properties.getLeafNodeGrouping(); + + _TC.getDAG().traverseDAG(node -> { + NamedElement elem = node.getElement(); + if (elem!=null) { + inferElementGrouping(_TC, topLevelGrouping, leafGrouping, node); + } + }); + } + + private static void inferElementGrouping(TranslationContext _TC, Grouping topLevelGrouping, Grouping leafGrouping, DAGNode node) { + // Check if grouping has already been set + if (node.getGrouping()!=null) return; + + // Get node model element + NamedElement elem = node.getElement(); + if (elem==null) return; // Root node? + + // Infer element grouping + Object groupingObj; + if (elem instanceof ServiceLevelObjective || elem instanceof Constraint) { + groupingObj = topLevelGrouping; + } else if (elem instanceof Sensor || elem instanceof RawMetricContext) { + groupingObj = leafGrouping; + } else { + // Infer parents' groupings + Set parents = _TC.getDAG().getParentNodes(node); + parents.forEach(p -> inferElementGrouping(_TC, topLevelGrouping, leafGrouping, p)); + + // Get the lowest parents grouping + List parentGroupings = parents.stream() + .filter(p -> p.getElement()!=null) + .map(DAGNode::getGrouping) + .collect(Collectors.toSet()).stream() + .filter(Objects::nonNull) + .sorted().toList(); + if (! parentGroupings.isEmpty()) + groupingObj = parentGroupings.get(0); + else + groupingObj = topLevelGrouping; + + // Get grouping in element specification (if provided) + if (elem.getObject() instanceof Map m) { + Object gObj = m.get("grouping"); + if (gObj == null) + gObj = m.get("level"); + if (gObj != null) { + Grouping specGrouping = Grouping.valueOf( gObj.toString().trim().toUpperCase() ); + if (specGrouping.ordinal() >= leafGrouping.ordinal()) { + if (specGrouping.ordinal() < Grouping.valueOf(groupingObj.toString().toUpperCase()).ordinal()) { + groupingObj = specGrouping; + } + } else { + groupingObj = leafGrouping; + } + } + } + } + node.setGrouping(Grouping.valueOf(groupingObj.toString().toUpperCase())); + } + +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelValidator.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelValidator.java new file mode 100644 index 0000000..b7fc954 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricModelValidator.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; +import com.helger.schematron.pure.SchematronResourcePure; +import com.helger.schematron.svrl.jaxb.FailedAssert; +import com.helger.schematron.svrl.jaxb.SchematronOutputType; +import com.helger.schematron.svrl.jaxb.Text; +import com.helger.xml.transform.StringStreamSource; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.stereotype.Service; + +import java.io.InputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class MetricModelValidator { + private static final String DEFAULT_SCHEMATRON_FILE = "classpath:metric-model-schematron.xml"; + + private final ResourceLoader resourceLoader; + + // ================================================================================================================ + // Model validation methods + + public void validateModel(@NonNull Object metricModel, String modelName) throws Exception { + log.debug("MetricModelValidator.validateModel(): Validating metric model: {}", metricModel); + + // -- Schematron Validation ------------------------------------------- + validateWithSchematron(metricModel, modelName); + + // -------------------------------------------------------------------- + + log.debug("MetricModelValidator.validateModel(): Validating metric model completed: {}", metricModel); + } + + // ======================================================================== + // Schematron validation + // ======================================================================== + + public void validateWithSchematron(Object modelObj, String modelName) throws Exception { + // ---------------------------------------------------------- + // Convert Map to XML + + XmlMapper mapper = new XmlMapper(); + mapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + String xmlStr = mapper + .writerWithDefaultPrettyPrinter() + .withRootName("metricModel") + .writeValueAsString(modelObj); + log.trace("SCHEMATRON: Validating metric model: {}", xmlStr); + + // ---------------------------------------------------------- + // Load Schematron rules + + String schematronFile = DEFAULT_SCHEMATRON_FILE; + Resource resource = resourceLoader.getResource(schematronFile); + SchematronResourcePure schRes; + try (InputStream is = resource.getInputStream()) { + schRes = SchematronResourcePure.fromInputStream(schematronFile, is); + if (!schRes.isValidSchematron()) + throw new IllegalArgumentException("Invalid Schematron file: " + schematronFile); + } + + // ---------------------------------------------------------- + // Validate model using schematron -- Alt. #1 + + // Check metric model validity + /*EValidity validity = schRes.getSchematronValidity(new StringStreamSource(xmlStr)); + boolean isMetricModelValid = validity.isValid(); + log.debug("SCHEMATRON: Metric model is valid: {}", isMetricModelValid); + log.debug("SCHEMATRON: Validity: {}", validity);*/ + + // ---------------------------------------------------------- + // Validate model using schematron -- Alt. #2 + + // Validate metric model and get failed asserts + SchematronOutputType schOutput = schRes.applySchematronValidationToSVRL(new StringStreamSource(xmlStr)); + assert schOutput != null; + List failedAsserts = schOutput.getActivePatternAndFiredRuleAndFailedAssert(); + int failedAssertsCount = 0; + for (Object object : failedAsserts) { + if (object instanceof FailedAssert failedAssert) { + failedAssertsCount++; + log.warn("SCHEMATRON: FAILED-ASSERT: {} -- {}", + failedAssert.getId(), //failedAssert.getTest(), + getSchematronDiagnosticMessages( failedAssert.getDiagnosticReferenceOrPropertyReferenceOrText() ) + ); + } + } + boolean isMetricModelValid = (failedAssertsCount == 0); + + // ---------------------------------------------------------- + // Report validation results + + log.debug("SCHEMATRON: Num. of asserts failed: {}", failedAssertsCount); + log.debug("SCHEMATRON: Metric model is valid: {}", isMetricModelValid); + + if (! isMetricModelValid) + throw new IllegalArgumentException ("Invalid Metric Model: "+modelName); + log.info("MetricModelValidator: Metric model is valid: {}", modelName); + } + + public List getSchematronDiagnosticMessages(Object o) { + if (o instanceof String s) { + s = s.replaceAll("[ \t\r\n]+", " ").trim(); + log.trace("SCHEMATRON: ----> STRING: {}", s); + return Collections.singletonList(s); + } else if (o instanceof Text t) { + log.trace("SCHEMATRON: ----> TEXT: {} = {}", t.getContentCount(), t.getContent().size()); + return t.getContent().stream().map(this::getSchematronDiagnosticMessages).flatMap(List::stream).toList(); + } else if (o instanceof Collection c) { + log.trace("SCHEMATRON: ----> COLLECTION: {}", c.size()); + return c.stream().flatMap(xx -> getSchematronDiagnosticMessages(xx).stream()).toList(); + } else { + log.trace("SCHEMATRON: ----> OTHER: {} {}", o.getClass(), o); + return Collections.singletonList(o.toString()); + } + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricsHelper.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricsHelper.java new file mode 100644 index 0000000..cc117b4 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/MetricsHelper.java @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import gr.iccs.imu.ems.brokercep.cep.MathUtil; +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.model.*; +import eu.nebulous.ems.translate.NebulousEmsTranslatorProperties; +import eu.nebulous.ems.translate.generate.RuleGenerator; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.*; + +// ------------------------------------------------------------------------ +// Metric decomposition methods +// ------------------------------------------------------------------------ + +@Slf4j +@Service +@RequiredArgsConstructor +class MetricsHelper extends AbstractHelper { + private final static String DEFAULT_METRIC_NAME_SUFFIX = "_METRIC"; + + private final NebulousEmsTranslatorProperties properties; + private final SensorsHelper sensorsHelper; + + MetricContext decomposeMetric(@NonNull TranslationContext _TC, Map metricSpec, NamesKey parentNamesKey, NamedElement parent) { + log.debug("decomposeMetric: ARGS: spec: {}, parent-name: {}, parent-elem: {}", metricSpec, parentNamesKey, parent); + + // Get needed fields + String metricName = getSpecName(metricSpec).toLowerCase(); + String metricType = getSpecField(metricSpec, "type"); + + NamesKey metricNamesKey = getNamesKey(metricSpec, metricName); + if ($$(_TC).metricsUsed.containsKey(metricNamesKey)) { + MetricContext cachedMetric = $$(_TC).metricsUsed.get(metricNamesKey); + _TC.getDAG().addNode(parent, cachedMetric); + return cachedMetric; + } + + // Infer metric type + if (StringUtils.isBlank(metricType)) { + boolean hasSensor = (metricSpec.get("sensor") != null); + boolean hasFormula = (metricSpec.get("formula") != null); + boolean hasConstant = (metricSpec.get("constant") != null); + boolean hasRef = (metricSpec.get("ref") != null); + + if ( hasSensor && !hasFormula && !hasConstant && !hasRef) metricType = "raw"; + else if (!hasSensor && hasFormula && !hasConstant && !hasRef) metricType = "composite"; + else if (!hasSensor && !hasFormula && hasConstant && !hasRef) metricType = "constant"; + else if (!hasSensor && !hasFormula && !hasConstant && hasRef) metricType = "ref"; + else + throw createException("Cannot infer type of metric '"+metricName+"': " + metricSpec); + } + + // If a 'constant' stop, because constants have already been registered + if ("constant".equals(metricType)) { + return null; + } + // ...else continue with metric decomposition + + // Delegate decomposition based on metric type + MetricContext metric = switch (metricType) { + case "raw" -> + decomposeRawMetric(_TC, metricSpec, parent); + case "composite" -> + decomposeCompositeMetric(_TC, metricSpec, parent); + case "ref" -> + processRef(_TC, metricSpec, parentNamesKey, parent); + default -> + throw createException("Unknown metric type '" + metricType + "' in metric '" + metricName + "': " + metricSpec); + }; + $$(_TC).metricsUsed.put(metricNamesKey, metric); + + // Set 'object' + metric.setObject(metricSpec); + + // Process template + MetricTemplate template = processMetricTemplate(metricSpec, metricNamesKey); + if (template!=null) + metric.getMetric().setMetricTemplate(template); + + // Check if it is a Busy-Status metric + if (getSpecBoolean(metricSpec, "busy-status", false)) { + log.trace("decomposeMetric: {}: It is a BUSY-STATUS metric", metricNamesKey.name()); + _TC.addBusyStatusMetric(metric.getName()); + + // Add a top-level node to connect busy-status metric + String busyStatusMetricName = + String.format(properties.getBusyStatusDestinationNameFormatter(), metric.getName()); + BusyStatusMetricVariable newMv = BusyStatusMetricVariable.builder() + .name(busyStatusMetricName) + .metricContext(metric) + .componentMetrics(List.of(metric.getMetric())) + .metricTemplate(metric.getMetric().getMetricTemplate()) + .build(); + log.debug("decomposeMetric: {}: New Busy-Status metric variable: {}", metricNamesKey.name(), newMv.getName()); + + // Update TC + _TC.addBusyStatusDestinationNameToMetricContextName(metric.getName(), busyStatusMetricName); + //_TC.addElementToNamePair(newMv, newMv.getName()); + _TC.getDAG().addTopLevelNode(newMv); + _TC.getDAG().addNode(newMv, metric); + log.trace("decomposeMetric: {}: New Busy-Status metric added to DAG: {}", metricNamesKey.name(), newMv.getName()); + } + + return metric; + } + + private RawMetricContext decomposeRawMetric(TranslationContext _TC, Map metricSpec, NamedElement parent) { + log.debug("decomposeRawMetric: ARGS: spec: {}, parent: {}", metricSpec, parent); + + // Get needed fields + String metricName = getSpecName(metricSpec); + Map sensorSpec = asMap(metricSpec.get("sensor")); + Map outputSpec = asMap(metricSpec.get("output")); + + NamesKey metricNamesKey = getNamesKey(metricSpec, metricName); + + // Update TC + RawMetricContext rawMetric = RawMetricContext.builder() + .name(metricNamesKey.name()) + .object(metricSpec) + .build(); + _TC.getDAG().addNode(parent, rawMetric); + + // Process child blocks + Sensor sensor = sensorsHelper.processSensor(_TC, sensorSpec, metricNamesKey, rawMetric); + Schedule schedule = outputSpec!=null + ? processSchedule(outputSpec, metricNamesKey) : null; + + // Complete TC update + rawMetric.setSensor(sensor); + rawMetric.setSchedule(schedule); + rawMetric.setMetric(RawMetric.builder() + .name(metricName + DEFAULT_METRIC_NAME_SUFFIX) + .build()); + + return rawMetric; + } + + private CompositeMetricContext decomposeCompositeMetric(TranslationContext _TC, Map metricSpec, NamedElement parent) { + log.debug("decomposeCompositeMetric: ARGS: spec: {}, parent: {}", metricSpec, parent); + + // Get needed fields + String metricName = getSpecName(metricSpec); + String formula = getMandatorySpecField(metricSpec, "formula", "Composite Metric '"+metricName+"' without 'formula': "); + Map windowSpec = asMap(metricSpec.get("window")); + Map outputSpec = asMap(metricSpec.get("output")); + + NamesKey metricNamesKey = getNamesKey(metricSpec, metricName); + + // Check formula and extract metrics + if (StringUtils.isBlank(formula)) + throw createException("Composite metric 'formula' cannot be blank: at '"+metricNamesKey.name()+"': " + metricSpec); + @NonNull Set formulaArgs = MathUtil.getFormulaArguments(formula); + log.trace("decomposeCompositeMetric: {}: formula={}, args={}", metricNamesKey.name(), formula, formulaArgs); + + // Remove constants and custom function names from 'formulaArgs' + String containerName = getContainerName(metricSpec); + formulaArgs.removeAll( $$(_TC).constants.keySet().stream() + .filter(nk -> nk.parent.equals(containerName)) // Check that all formula args are metrics under the same parent + .map(nk->nk.child) + .collect(Collectors.toSet())); + formulaArgs.removeAll( $$(_TC).functionNames ); + log.trace("decomposeCompositeMetric: {}: After removing constants: formula={}, args={}", metricNamesKey.name(), formula, formulaArgs); + + // Update TC + CompositeMetricContext compositeMetric = CompositeMetricContext.builder() + .name(metricNamesKey.name()) + .object(metricSpec) + .build(); + _TC.getDAG().addNode(parent, compositeMetric); + + // Decompose to metrics used in formula (i.e. composing or child metrics) + // NOTE: child metric decomposition MUST be done before this metric has been altered in any way (or else + // hashCode() will return new value, different from that cached in the DAG) + List childMetricsList = new ArrayList<>(); + for (String childMetricName : formulaArgs) { + NamesKey childMetricNamesKey = getNamesKey(metricSpec, childMetricName); + MetricContext childMetric = decomposeMetric( + _TC, asMap($$(_TC).allMetrics.get(childMetricNamesKey)), metricNamesKey, compositeMetric); + if (childMetric!=null) + childMetricsList.add(childMetric); + } + compositeMetric.setComposingMetricContexts(childMetricsList); + + // Process child blocks + Window window = windowSpec!=null + ? processWindow(windowSpec, metricNamesKey) : null; + Schedule schedule = outputSpec!=null + ? processSchedule(outputSpec, metricNamesKey) : null; + + // Complete TC update + compositeMetric.setWindow(window); + compositeMetric.setSchedule(schedule); + compositeMetric.setMetric(CompositeMetric.builder() + .name(metricName + DEFAULT_METRIC_NAME_SUFFIX) + .formula(formula) + .componentMetrics(childMetricsList.stream().map(MetricContext::getMetric).toList()) + .build()); + + return compositeMetric; + } + + private MetricContext processRef(TranslationContext _TC, Map metricSpec, NamesKey parentNamesKey, NamedElement parent) { + // Get needed fields + String refStr = getMandatorySpecField(metricSpec, "ref", "Metric reference must provide a value for 'ref' field: at metric '" + parentNamesKey.name() + "': " + metricSpec); + + // Process 'ref' + refStr = refStr.replace("[", "").replace("]", ""); + NamesKey referencedNamesKey = NamesKey.isFullName(refStr) + ? NamesKey.create(refStr) : NamesKey.create(parentNamesKey.parent, refStr); + MetricContext referencedMetric = $$(_TC).metricsUsed.get(referencedNamesKey); + if (referencedMetric==null) { + Object spec = $$(_TC).allMetrics.get(referencedNamesKey); + if (spec==null) + throw createException("Cannot find referenced metric '"+referencedNamesKey.name()+"': " + metricSpec); + referencedMetric = decomposeMetric(_TC, asMap(spec), parentNamesKey, parent); + // 'decomposeMetric' will take care to add referencedMetric into the DAG + } else { + // add a new edge to the referencedMetric in the DAG + _TC.getDAG().addNode(parent, referencedMetric); + } + + return referencedMetric; + } + + void processConstant(TranslationContext _TC, Map metricSpec, String parentName) { + // Get needed fields + String metricName = getSpecName(metricSpec); + Double defaultValue = getSpecNumber(metricSpec, "default"); + + NamesKey metricNamesKey = NamesKey.create(parentName, metricName); + + // Register metric constant, and initial value (if available) + $$(_TC).constants.put(metricNamesKey, defaultValue); + if (defaultValue!=null) + _TC.addConstantDefault(metricName, defaultValue); + } + + private MetricTemplate processMetricTemplate(Map metricSpec, NamesKey parentNamesKey) { + Object templateObj = metricSpec.get("template"); + if (templateObj instanceof Map templateSpec) { + String id = getSpecField(templateSpec, "id"); + String type = getMandatorySpecField(templateSpec, "type", + "Metric template without 'type': at metric '" + parentNamesKey.name() + "': " + metricSpec); + ValueType valueType = ValueType.valueOf(type.trim().toUpperCase() + "_TYPE"); + String dirStr = getSpecField(templateSpec, "direction"); + short valueDirection = StringUtils.isNotBlank(dirStr) + ? Short.parseShort(dirStr.trim()) : MetricTemplate.FORWARD_DIRECTION; + List range = asList(templateSpec.get("range")); + List values = asList(templateSpec.get("values")); + String unit = getSpecField(templateSpec, "unit"); + + if (range!=null && (range.size()!=2 || range.get(0)==null || range.get(1)==null)) + throw createException("Invalid range spec in metric template: "+metricSpec); + if (range!=null && ! AnalysisUtils.isDoubleOrInfinity(range.get(0).toString())) + throw createException("Invalid lower range bound in metric template: "+metricSpec); + if (range!=null && ! AnalysisUtils.isDoubleOrInfinity(range.get(1).toString())) + throw createException("Invalid upper range bound in metric template: "+metricSpec); + double lowerBound = range!=null ? AnalysisUtils.getDoubleValue(range.get(0).toString().trim()) : Double.NEGATIVE_INFINITY; + double upperBound = range!=null ? AnalysisUtils.getDoubleValue(range.get(1).toString().trim()) : Double.POSITIVE_INFINITY; + if (lowerBound > upperBound) + throw createException("Lower range bound > upper range bound in metric template: "+metricSpec); + + values = values!=null ? values.stream().filter(Objects::nonNull).toList() : null; + if (values!=null && values.isEmpty()) values = null; + + return MetricTemplate.builder() + .object(templateSpec) + .name(id) + .valueType(valueType) + .valueDirection(valueDirection) + .unit(unit) + .lowerBound(lowerBound) + .upperBound(upperBound) + .allowedValues(values) + .build(); + } + return null; + } + + void processOrphanMetrics(TranslationContext _TC) { + if (properties.isIncludeOrphanMetrics()) { + HashSet orphanMetrics = new HashSet<>($$(_TC).allMetrics.keySet()); + orphanMetrics.removeAll($$(_TC).metricsUsed.keySet()); + orphanMetrics.removeAll($$(_TC).constants.keySet()); + log.debug("Orphan metrics: {}", orphanMetrics); + + MetricVariable metricVar = MetricVariable.builder() + .name(properties.getOrphanMetricsParentName()) + .build(); + _TC.getDAG().addTopLevelNode(metricVar); + orphanMetrics.forEach(metricNamesKey -> { + Map metricSpec = asMap($$(_TC).allMetrics.get(metricNamesKey)); + String parentName = getContainerName(metricSpec); + NamesKey parentNamesKey = NamesKey.create(parentName, "DUMMY"); + decomposeMetric(_TC, metricSpec, parentNamesKey, metricVar); + }); + } + } + + + // ------------------------------------------------------------------------ + // Window block processing methods + // ------------------------------------------------------------------------ + + private Window processWindow(Map windowSpec, NamesKey metricNamesKey) { + // Get window type + String typeStr = getMandatorySpecField(windowSpec, "type", "Window without 'type': at metric '"+metricNamesKey+"': "); + WindowType windowType = WindowType.valueOf(typeStr.toUpperCase()); + + // Get window size + Map sizeMap = asMap(windowSpec.get("size")); + String sizeTypeStr = getSpecField(sizeMap, "type"); + Object valueObj = sizeMap.get("value"); + String unitStr = getSpecField(sizeMap, "unit"); + + // Check window size value + if (!(valueObj instanceof Number) && !(valueObj instanceof String)) + throw createException("Window size value is mandatory and MUST be a positive integer: at metric '" + metricNamesKey + "': " + windowSpec); + long value = valueObj instanceof Number n + ? n.longValue() : Long.parseLong(valueObj.toString()); + if (value<=0) + throw createException("Window size value cannot be zero or negative: at metric '" + metricNamesKey + "': " + windowSpec); + + // Check window size (time) unit + ChronoUnit unit = StringUtils.isNotBlank(unitStr) + ? normalizeTimeUnit(unitStr) : ChronoUnit.SECONDS; + + // Get or infer window size type + WindowSizeType sizeType; + if (StringUtils.isNotBlank(sizeTypeStr)) + sizeType = WindowSizeType.valueOf(sizeTypeStr.trim().toUpperCase()); + else + sizeType = (unit !=null) ? WindowSizeType.TIME_ONLY : WindowSizeType.MEASUREMENTS_ONLY; + + // Initialize size parameters + long measurementSize = -1; + long timeSize = -1; + String timeUnit = null; + if (sizeType!=WindowSizeType.MEASUREMENTS_ONLY) { + timeSize = value; + timeUnit = unit.toString(); + } + if (sizeType!=WindowSizeType.TIME_ONLY) { + measurementSize = value; + } + + // Process any 'processing' blocks + List processingSpecs = asList(windowSpec.get("processing")); + List processingsList = null; + if (processingSpecs!=null) { + for (Object processingObj : processingSpecs) { + WindowProcessing processing = processProcessing(asMap(processingObj), metricNamesKey); + if (processingsList==null) + processingsList = new ArrayList<>(); + processingsList.add(processing); + } + } + + return Window.builder() + .object(windowSpec) + .windowType(windowType) + .sizeType(sizeType) + .measurementSize(measurementSize) + .timeSize(timeSize) + .timeUnit(timeUnit) + .processings(processingsList) + .subFeatures(getTranslationFeature(windowSpec)) + .build(); + } + + private WindowProcessing processProcessing(Map processingSpec, NamesKey metricNamesKey) { + // Get processing type + String typeStr = getMandatorySpecField(processingSpec, "type", "Window Processing without 'type': at metric '"+metricNamesKey+"': "); + WindowProcessingType processingType = WindowProcessingType.valueOf(typeStr.trim().toUpperCase()); + + // Process any 'criteria' blocks + List criteriaSpecs = asList(processingSpec.get("criteria")); + List criteriaList = null; + if (criteriaSpecs!=null) { + for (Object criterionObj : criteriaSpecs) { + WindowCriterion criterion = processCriterion(criterionObj, metricNamesKey); + if (criteriaList==null) + criteriaList = new ArrayList<>(); + criteriaList.add(criterion); + } + } + + return WindowProcessing.builder() + .object(processingSpec) + .processingType(processingType) + .groupingCriteria( processingType==WindowProcessingType.GROUP ? criteriaList : null ) + .rankingCriteria( processingType!=WindowProcessingType.GROUP ? criteriaList : null ) + .subFeatures(getTranslationFeature(processingSpec)) + .build(); + } + + private WindowCriterion processCriterion(Object criterionSpec, NamesKey metricNamesKey) { + if (criterionSpec instanceof String typeStr) { + CriterionType criterionType = CriterionType.valueOf(typeStr); + if (criterionType!=CriterionType.CUSTOM) + return WindowCriterion.builder() + .type(criterionType).build(); + else + throw createException("Window Criterion of '"+criterionType+"' type cannot be a string: at metric '" + metricNamesKey + "': " + criterionSpec); + } + + if (criterionSpec instanceof Map) { + // Get processing type + String typeStr = getMandatorySpecField(criterionSpec, "type", "Window Criterion without 'type': at metric '"+metricNamesKey+"': "); + CriterionType criterionType = CriterionType.valueOf(typeStr); + + // Get 'custom' field (if CUSTOM) + String custom = null; + if (criterionType==CriterionType.CUSTOM) { + custom = getMandatorySpecField(criterionSpec, "custom", + "CUSTOM window criterion must provide 'custom' field: at metric '" + metricNamesKey + "': "); + } + + // Get sort direction (ascending, or descending) + String ascStr = getSpecField(criterionSpec, "ascending"); + boolean isAscending = getBooleanValue(ascStr.trim(), true); + + return WindowCriterion.builder() + .object(criterionSpec) + .type(criterionType) + .custom(custom) + .ascending(isAscending) + .build(); + } + + throw createException("Window Criterion specification not supported: at metric '" + metricNamesKey + "': " + criterionSpec); + } + + private List getTranslationFeature(Map spec) { + String eplStr = getSpecField(spec, "epl"); + String functionStr = getSpecField(spec, "function"); + if (StringUtils.isBlank(eplStr)) + eplStr = functionStr; + + if (StringUtils.isNotBlank(eplStr)) { + Attribute eplAttr = Attribute.builder() + .name(RuleGenerator.EPL_VALUE) + .valueType(ValueType.STRING_TYPE) + .value(eplStr) + .build(); + List translationAttributes = List.of(eplAttr); + + Feature translationFeature = Feature.builder() + .name(RuleGenerator.TRANSLATION_CONFIG) + .attributes(translationAttributes) + .build(); + return List.of(translationFeature); + } + return null; + } + + // ------------------------------------------------------------------------ + // Schedule block processing methods + // ------------------------------------------------------------------------ + + private Schedule processSchedule(Map scheduleSpec, NamesKey metricNamesKey) { + // Get needed fields + String type = getSpecField(scheduleSpec, "type"); + if (StringUtils.isBlank(type)) type = "all"; + + // Get 'schedule' + Map schedMap = asMap(scheduleSpec.get("schedule")); + + // Get schedule value + Object valueObj = schedMap.get("value"); + long interval; + if (!(valueObj instanceof Number) && !(valueObj instanceof String)) + throw createException("Schedule value is mandatory and MUST be a positive integer: at metric '" + metricNamesKey.name() + "': " + scheduleSpec); + else + interval = (valueObj instanceof Number n) ? n.longValue() : Long.parseLong(valueObj.toString()); + if (interval<=0) + throw createException("Schedule value cannot be zero or negative: at metric '" + metricNamesKey.name() + "': " + scheduleSpec); + + // Get schedule unit + String unitStr = getSpecField(schedMap, "unit"); + ChronoUnit unit = StringUtils.isNotBlank(unitStr) + ? normalizeTimeUnit(unitStr) : ChronoUnit.SECONDS; + + return Schedule.builder() + .object(scheduleSpec) + .interval(interval) + .timeUnit(unit.toString()) + .type(Schedule.SCHEDULE_TYPE.valueOf(type.trim().toUpperCase())) + .build(); + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NamesKey.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NamesKey.java new file mode 100644 index 0000000..a539a0f --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NamesKey.java @@ -0,0 +1,34 @@ +package eu.nebulous.ems.translate.analyze; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; + +@ToString +@EqualsAndHashCode +@RequiredArgsConstructor(staticName = "create") +public class NamesKey { + public final String parent; + public final String child; + + public static NamesKey create(String s) { + if (!isFullName(s)) + throw new IllegalArgumentException("Argument is not a full name (i.e. .): "+s); + String[] part = s.split("\\."); + if (part.length!=2) + throw new IllegalArgumentException("Argument is not a valid full name (i.e. .): "+s); + if (StringUtils.isBlank(part[0]) || StringUtils.isBlank(part[1])) + throw new IllegalArgumentException("Argument is not a valid full name. Parent or Child name is blank: "+s); + return create(part[0], part[1]); + } + + public static boolean isFullName(String s) { + if (StringUtils.isBlank(s)) return false; + return s.contains("."); + } + + public String name() { + return parent+"."+child; + } +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NodeUpdatingHelper.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NodeUpdatingHelper.java new file mode 100644 index 0000000..346b763 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/NodeUpdatingHelper.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import eu.nebulous.ems.translate.NebulousEmsTranslatorProperties; +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.dag.DAGNode; +import gr.iccs.imu.ems.translate.model.BusyStatusMetricVariable; +import gr.iccs.imu.ems.translate.model.MetricVariable; +import gr.iccs.imu.ems.translate.model.NamedElement; +import gr.iccs.imu.ems.translate.model.ServiceLevelObjective; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.createException; +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.getContainerName; + +// ------------------------------------------------------------------------ +// DAG node updating with requiring components, and SLO per component +// grouping methods +// ------------------------------------------------------------------------ + +@Slf4j +@Service +@RequiredArgsConstructor +class NodeUpdatingHelper extends AbstractHelper { + private final NebulousEmsTranslatorProperties properties; + + void buildComponentsToSLOsMap(TranslationContext _TC, DocumentContext ctx, Set componentNames) { + // Group SLOs per component or scope + ConcurrentMap> componentOrScopesToSLOsMapping = $$(_TC).allSLOs.entrySet().stream() + .collect(Collectors.groupingByConcurrent( + entry -> getContainerName(entry.getValue()), + Collectors.mapping(Map.Entry::getKey, Collectors.toSet()))); + log.trace("MetricModelAnalyzer.analyzeModel(): componentOrScopesToSLOsMapping: {}", componentOrScopesToSLOsMapping); + + // Build component-to-scope mapping + Map> componentsToScopesMap = createComponentsToScopesMapping(ctx, componentNames); + log.trace("MetricModelAnalyzer.analyzeModel(): componentsToScopesMap: {}", componentsToScopesMap); + + // Build integrated components SLO sets + Map> componentsToSLOsMap = componentNames.stream() + .collect(Collectors.toMap( + Function.identity(), + componentName -> { + Set componentScopes = new LinkedHashSet<>(componentsToScopesMap.get(componentName)); + componentScopes.add(componentName); + return componentScopes.stream() + .map(componentOrScopesToSLOsMapping::get) + .map(set -> set!=null ? set : new LinkedHashSet()) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + } + )); + log.trace("MetricModelAnalyzer.analyzeModel(): componentsToSLOsMap: {}", componentsToSLOsMap); + + $$(_TC).componentsToSLOsMap = componentsToSLOsMap; + } + + Map> createComponentsToScopesMapping(DocumentContext ctx, Set componentNames) { + Map> componentToScopeMap = new LinkedHashMap<>(); + ctx.read("$.spec.scopes.*", List.class).stream().filter(Objects::nonNull).forEach(scope -> { + // Get scope name and scope components + String scopeName = JsonPath.read(scope, "$.name").toString(); + Object oComponents = ((Map)scope).get("components"); + + // Process scope components spec + Set includedComponents = componentNames; + if (oComponents instanceof String s) + includedComponents = Arrays.stream(s.split(",")) + .map(String::trim).filter(str->!str.isBlank()) + .collect(Collectors.toSet()); + if (oComponents instanceof List l) + includedComponents = ((List) l).stream().filter(Objects::nonNull) + .filter(i->i instanceof String).map(i -> i.toString().trim()) + .filter(str -> !str.isBlank()).collect(Collectors.toSet()); + if (includedComponents.isEmpty()) + includedComponents = componentNames; + Set notFound = includedComponents.stream() + .filter(i -> !componentNames.contains(i)).collect(Collectors.toSet()); + if (!notFound.isEmpty()) + throw createException("Scope component(s) "+notFound+" have not been specified in scope: "+scopeName); + + // Update results map + includedComponents.forEach(componentName -> componentToScopeMap + .computeIfAbsent(componentName, name -> new LinkedHashSet<>()) + .add(scopeName)); + }); + log.trace("Components-to-Scopes map: {}", componentToScopeMap); + return componentToScopeMap; + } + + void buildSLOToComponentsMap(TranslationContext _TC) { + ConcurrentMap> slosToComponentsMap = $$(_TC).componentsToSLOsMap.entrySet().stream() + .map(entry -> entry.getValue().stream() + .map(x -> new AbstractMap.SimpleEntry<>(entry.getKey(), x)) + .toList()) + .flatMap(Collection::stream) + .collect(Collectors.groupingByConcurrent( + AbstractMap.SimpleEntry::getValue, + Collectors.mapping(AbstractMap.SimpleEntry::getKey, Collectors.toSet()) + )); + log.trace("MetricModelAnalyzer.analyzeModel(): slosToComponentsMap: {}", slosToComponentsMap); + + $$(_TC).slosToComponentsMap = slosToComponentsMap; + } + + void updateDAGNodesWithComponents(TranslationContext _TC, Set componentNames) { + _TC.getDAG().getTopLevelNodes().forEach(tlNode -> { + if (tlNode.getElement() instanceof ServiceLevelObjective slo) { + Set components = $$(_TC).slosToComponentsMap.get(NamesKey.create(slo.getName())); + log.trace("Updating DAG node components: slo-name={}, slo-components={}", slo.getName(), components); + tlNode.getProperties().put("components", components); + updateComponents(_TC, tlNode); + } else if (tlNode.getElement() instanceof BusyStatusMetricVariable bsMv) { + if (log.isTraceEnabled()) + log.trace("Updating DAG node components: BS-name={}, BS-components={}, BS-metric={}", + bsMv.getName(), componentNames, + _TC.getDAG().getNodeChildren(tlNode).stream() + .map(DAGNode::getElement).map(NamedElement::getName).toList()); + tlNode.getProperties().put("components", componentNames); + _TC.getDAG().getNodeChildren(tlNode).forEach(bsMetricNode -> { + bsMetricNode.getProperties().put("components", componentNames); + updateComponents(_TC, bsMetricNode); + }); + } else if (tlNode.getElement() instanceof MetricVariable mv && + StringUtils.equalsIgnoreCase(tlNode.getName(), properties.getOrphanMetricsParentName())) + { + if (log.isTraceEnabled()) + log.trace("Updating DAG node components: Orphan metrics: {}", + _TC.getDAG().getNodeChildren(tlNode).stream() + .map(DAGNode::getElement).map(NamedElement::getName).toList()); + _TC.getDAG().getNodeChildren(tlNode).forEach(bsMetricNode -> { + bsMetricNode.getProperties().put("components", componentNames); + updateComponents(_TC, bsMetricNode); + }); + } else { + log.error("ERROR: Updating DAG node components: Unexpected top-level DAG node encountered: {}", + tlNode.getElement()!=null ? tlNode.getElement().getName()+" "+tlNode.getElement().getClass() : null); + throw createException("Unexpected top-level DAG node encountered: " + tlNode); + } + }); + + // Traverse DAG and log node components + log.debug("DAG node components: traversing DAG..."); + _TC.getDAG().traverseDAG(node -> log.debug("-----> {} :: {}", node.getName(), node.getProperties().get("components"))); + } + + private void updateComponents(TranslationContext _TC, DAGNode parentNode) { + Set parentComponents = (Set) parentNode.getProperties().get("components"); + if (parentComponents==null) + throw createException("Parent 'components' property has not been set: "+parentNode); + _TC.getDAG().getNodeChildren(parentNode).forEach(node -> { + Set componentsSet = (Set) node.getProperties() + .computeIfAbsent("components", k -> new LinkedHashSet<>()); + log.trace("Updating DAG node components: ... node-name={}, node-components BEFORE={}", node.getName(), componentsSet); + int s1 = componentsSet.size(); + componentsSet.addAll(parentComponents); + log.trace("Updating DAG node components: ... node-name={}, node-components AFTER={}", node.getName(), componentsSet); + if (s1!=componentsSet.size()) + updateComponents(_TC, node); + else + log.trace("Updating DAG node components: ... No further decomposition required: {}", node.getName()); + }); + } + + void removeCommonOrphanMetricsParent(TranslationContext _TC) { + DAGNode orphanMetricsNode = _TC.getDAG().getTopLevelNodes().stream() + .filter(tlNode -> tlNode.getElement() instanceof MetricVariable + && StringUtils.equalsIgnoreCase(tlNode.getName(), properties.getOrphanMetricsParentName())) + .findAny().orElse(null); + log.trace("MetricModelAnalyzer.analyzeModel(): orphanMetricsNode: {}", orphanMetricsNode); + + if (orphanMetricsNode != null) { + DAGNode root = _TC.getDAG().getRootNode(); + _TC.getDAG().getNodeChildren(orphanMetricsNode).forEach(node -> { + log.trace("MetricModelAnalyzer.analyzeModel(): Making orphan metric top-level: {}", node); + _TC.getDAG().addDAGEdge(root, node); + _TC.getDAG().removeEdge(orphanMetricsNode, node); + }); + } + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/SensorsHelper.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/SensorsHelper.java new file mode 100644 index 0000000..4687299 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/SensorsHelper.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import eu.nebulous.ems.translate.NebulousEmsTranslatorProperties; +import eu.nebulous.ems.translate.plugins.SensorPostProcessorPlugin; +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.dag.DAGNode; +import gr.iccs.imu.ems.translate.model.*; +import gr.iccs.imu.ems.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.*; + +// ------------------------------------------------------------------------ +// Sensor processing methods +// ------------------------------------------------------------------------ + +@Slf4j +@Service +@RequiredArgsConstructor +class SensorsHelper extends AbstractHelper implements InitializingBean { + private static final String DEFAULT_SENSOR_NAME_SUFFIX = "_SENSOR"; + private static final String DEFAULT_SENSOR_TYPE = "netdata"; + + private final NebulousEmsTranslatorProperties properties; + private final List sensorPostProcessorPlugins; + private final Map sensorTypePluginsRegistry = new LinkedHashMap<>(); + + @Override + public void afterPropertiesSet() { + log.debug("SensorsHelper: Found sensor post-processor plugins: {}", sensorPostProcessorPlugins); + sensorPostProcessorPlugins.forEach(plugin -> { + List types = plugin.getSupportedTypes(); + if (types!=null && !types.isEmpty()) { + List typesNormalized = types.stream().map(String::trim).map(String::toLowerCase).toList(); + if (typesNormalized.stream().anyMatch(sensorTypePluginsRegistry::containsKey)) { + throw new IllegalArgumentException(this.getClass().getName() + + " supports at least one sensor type that is already registered: " + + " this.types="+types+", registered-types="+sensorTypePluginsRegistry.keySet() + ); + } + // Supported types have not been previously registered + + typesNormalized.forEach(type->{ + sensorTypePluginsRegistry.put(type, plugin); + log.debug("SensorsHelper: Registered sensor type: type={}, plugin={}", type, plugin.getClass()); + }); + } + }); + log.debug("SensorsHelper: Sensor Type Registry: {}", sensorTypePluginsRegistry); + } + + Sensor processSensor(TranslationContext _TC, Map sensorSpec, NamesKey parentNamesKey, NamedElement parent) { + // Get needed fields + String sensorName = getSpecName(sensorSpec); + String sensorType = getSpecField(sensorSpec, "type"); + if (StringUtils.isBlank(sensorName)) sensorName = parentNamesKey.child + DEFAULT_SENSOR_NAME_SUFFIX; + if (StringUtils.isBlank(sensorType)) sensorType = DEFAULT_SENSOR_TYPE; + + NamesKey sensorNamesKey = createNamesKey(parentNamesKey, sensorName); + + // Get 'push' or 'pull' type + boolean isPush = getBooleanValue(getSpecField(sensorSpec, "push"), false); + boolean isPull = getBooleanValue(getSpecField(sensorSpec, "pull"), false); + if (isPush && isPull) + throw createException("Sensor cannot be both 'push' and 'pull': sensor '" + sensorName + "' in metric '" + parentNamesKey + "': " + sensorSpec); + if (!isPush && !isPull) + isPull = true; + + // Get configuration + LinkedHashMap configuration = new LinkedHashMap<>(); + + Object mapping = sensorSpec.get("mapping"); + Object configObj = sensorSpec.get("config"); + Object installObj = sensorSpec.get("install"); + if (configObj!=null) + configuration.putAll(asMap(configObj)); + if (mapping instanceof String s && StringUtils.isNotBlank(s)) + configuration.put("mapping", s.trim()); + if (installObj instanceof Map i && !i.isEmpty()) + configuration.put("install", i); + + // overrides 'type' in 'config' (if any) + configuration.put("type", sensorType); + + // Create pull or push sensor + Sensor sensor; + if (isPull) { + sensor = createPullSensor(sensorSpec, sensorName, sensorNamesKey, configuration); + } else { + sensor = createPushSensor(sensorSpec, sensorName, sensorNamesKey, configuration); + } + sensor.setConfigurationStr( configObj instanceof String s ? s : null ); + sensor.setConfiguration( configuration ); + + // Call type-specific plugin (if any) to post-process sensor definition + postProcessSensor(sensor, sensorType, sensorSpec); + + // Update TC + DAGNode sensorNode = _TC.getDAG().addNode(parent, sensor); + + // Add component-sensor pair + Map metricSpec = asMap($$(_TC).allMetrics.get(parentNamesKey)); + String componentName = getContainerName(metricSpec); + ObjectContext objCtx = $$(_TC).objectContexts.get(componentName); + _TC.addComponentSensorPair(objCtx, sensor); + + // Add sensor monitor(s) + _TC.addMonitorsForSensor(sensorNamesKey.name(), _createMonitorsForSensor(_TC, objCtx, sensor, sensorNode)); + + return sensor; + } + + private Sensor createPullSensor(Map sensorSpec, String sensorName, NamesKey sensorNamesKey, LinkedHashMap configuration) { + // Convert Map to Map + Map cfgMapWithStr = configuration.entrySet().stream() + .filter(e -> e.getValue() != null) + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString())); + + // Get pull sensor configuration + String className = StrUtil.getWithVariations(cfgMapWithStr, "className", "").trim(); + String intervalPeriodStr = StrUtil.getWithVariations(cfgMapWithStr, "intervalPeriod", "").trim(); + String intervalUnitStr = StrUtil.getWithVariations(cfgMapWithStr, "intervalUnit", "").trim(); + + // Get interval + int period = StrUtil.strToInt(intervalPeriodStr, + (int)properties.getSensorDefaultInterval(), (i)->i>=properties.getSensorMinInterval(), false, + String.format(" createPullSensor(): Invalid interval period in configuration: sensor=%s, configuration=%s\n", + sensorName, cfgMapWithStr)); + Interval.UnitType periodUnit = StrUtil.strToEnum(intervalUnitStr, + Interval.UnitType.class, Interval.UnitType.SECONDS, false, + String.format(" createPullSensor(): Invalid interval unit in configuration: sensor=%s, configuration=%s\n", + sensorName, cfgMapWithStr)); + Interval interval = Interval.builder() + .period(period) + .unit(periodUnit) + .build(); + + // Create pull sensor + return PullSensor.builder() + .name(sensorNamesKey.name()) + .object(sensorSpec) + .isPush(false) + .className(className) + .interval(interval) + .build(); + } + + private static Sensor createPushSensor(Map sensorSpec, String sensorName, NamesKey sensorNamesKey, LinkedHashMap configuration) { + // Get push sensor port + Object portObj = configuration.get("port"); + String portStr = portObj!=null ? portObj.toString().trim() : ""; + if (StringUtils.isBlank(portStr)) portStr = null; + int port = StrUtil.strToInt(portStr, -1, (i)->i>0 && i<=65535, false, + String.format(" createPushSensor(): ERROR: Invalid port. Using -1: sensor=%s, port=%s\n", sensorName, portStr)); + + // Create push sensor + return PushSensor.builder() + .name(sensorNamesKey.name()) + .object(sensorSpec) + .isPush(true) + .port(port) + .build(); + } + + private Set _createMonitorsForSensor(TranslationContext _TC, ObjectContext objectContext, Sensor sensor, DAGNode sensorNode) { + log.debug(" _createMonitorsForSensor(): sensor={}", sensor.getName()); + + // Check if sensor monitors have already been created + if (_TC.containsMonitorsForSensor(sensor.getName())) { + log.debug(" _createMonitorsForSensor(): sensor={} :: Monitors for this sensor have already been added", sensor.getName()); + return Collections.emptySet(); + } + + // Get monitor component + String componentName = (objectContext!=null && objectContext.getComponent()!=null) + ? objectContext.getComponent().getName() : null; + + // Create results set + Set results = new HashSet<>(); + for (DAGNode parent : _TC.getDAG().getParentNodes(sensorNode)) { + // Get metric name from sensor + log.debug(" + _createMonitorsForSensor(): sensor={} :: parent-node={}", sensor.getName(), parent.getName()); + /*Map rawMetricSpec = asMap(parent.getElement().getObject()); + String metricName = getSpecName(rawMetricSpec);*/ + String metricName = sensor.getName(); + log.debug(" + _createMonitorsForSensor(): sensor={} :: topic={}, component={}", sensor.getName(), metricName, componentName); + + // Create a Monitor instance + Monitor monitor = Monitor.builder() + .metric(metricName) + .sensor(sensor) + .component(componentName) + .build(); + // watermark will be set in Coordinator + + results.add(monitor); + } + log.debug(" _createMonitorsForSensor(): sensor={} :: monitors={}", sensor.getName(), results); + + return results; + } + + private void postProcessSensor(Sensor sensor, String sensorType, Map sensorSpec) { + String type = StringUtils.defaultIfBlank(sensorType, DEFAULT_SENSOR_TYPE).trim().toLowerCase(); + SensorPostProcessorPlugin plugin = sensorTypePluginsRegistry.get(type); + if (plugin==null) { + log.debug("SensorsHelper: postProcessSensor: No post-processor plugin found for sensor type: {}", sensorType); + } else { + log.debug("SensorsHelper: postProcessSensor: Calling post-processor plugin: type={}, plugin={}", sensorType, plugin); + plugin.postProcessSensor(sensor, sensorType, sensorSpec); + } + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ShorthandsExpansionHelper.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ShorthandsExpansionHelper.java new file mode 100644 index 0000000..5cd4aeb --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/analyze/ShorthandsExpansionHelper.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.analyze; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.ParseContext; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static eu.nebulous.ems.translate.analyze.AnalysisUtils.*; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ShorthandsExpansionHelper { + private final static Pattern METRIC_CONSTRAINT_PATTERN = + Pattern.compile("^([^<>=!]+)([<>]=|=[<>]|<>|!=|[=><])(.+)$"); + private final static Pattern METRIC_WINDOW_PATTERN = + Pattern.compile("^\\s*(\\w+)\\s+(\\d+(?:\\.\\d*)?|\\.\\d+)\\s*(?:(\\w+)\\s*)?"); + private final static Pattern METRIC_WINDOW_SIZE_PATTERN = + Pattern.compile("^\\s*(\\d+(?:\\.\\d*)?|\\.\\d+)\\s*(?:(\\w+)\\s*)?"); + private final static Pattern METRIC_OUTPUT_PATTERN = + Pattern.compile("^\\s*(\\w+)\\s+(\\d+(?:\\.\\d*)?|\\.\\d+)\\s*(\\w+)\\s*"); + private final static Pattern METRIC_OUTPUT_SCHEDULE_PATTERN = + Pattern.compile("^\\s*(\\d+(?:\\.\\d*)?|\\.\\d+)\\s*(\\w+)\\s*"); + private final static Pattern METRIC_SENSOR_PATTERN = + Pattern.compile("^\\s*(\\w+)\\s+(\\w+)\\s*"); + + // ------------------------------------------------------------------------ + // Methods for expanding shorthand expressions + // ------------------------------------------------------------------------ + + public void expandShorthandExpressions(Object metricModel, String modelName) throws Exception { + log.debug("ShorthandsExpansionHelper: model-name: {}", modelName); + + // -- Initialize jsonpath context ------------------------------------- + Configuration jsonpathConfig = Configuration.defaultConfiguration(); + ParseContext parseContext = JsonPath.using(jsonpathConfig); + DocumentContext ctx = parseContext.parse(metricModel); + + // ----- Expand SLO constraints ----- + List expandedConstraints = asList(ctx + .read("$.spec.*.*.requirements.*[?(@.constraint)]", List.class)).stream() + .filter(item -> JsonPath.read(item, "$.constraint") instanceof String) + .peek(this::expandConstraint) + .toList(); + log.debug("ShorthandsExpansionHelper: Constraints expanded: {}", expandedConstraints); + + // ----- Expand Metric windows ----- + List expandedWindows = asList(ctx + .read("$.spec.*.*.metrics.*[?(@.window)]", List.class)).stream() + .filter(item -> JsonPath.read(item, "$.window") instanceof String) + .peek(this::expandWindow) + .toList(); + log.debug("ShorthandsExpansionHelper: Windows expanded: {}", expandedWindows); + + List expandedWindowSizes = asList(ctx + .read("$.spec.*.*.metrics.*.window[?(@.size)]", List.class)).stream() + .filter(item -> JsonPath.read(item, "$.size") instanceof String) + .peek(this::expandWindowSize) + .toList(); + log.debug("ShorthandsExpansionHelper: Windows sizes expanded: {}", expandedWindowSizes); + + // ----- Expand Metric outputs ----- + List expandedOutputs = asList(ctx + .read("$.spec.*.*.metrics.*[?(@.output)]", List.class)).stream() + .filter(item -> JsonPath.read(item, "$.output") instanceof String) + .peek(this::expandOutput) + .toList(); + log.debug("ShorthandsExpansionHelper: Outputs expanded: {}", expandedOutputs); + + List expandedOutputSchedules = asList(ctx + .read("$.spec.*.*.metrics.*.output[?(@.schedule)]", List.class)).stream() + .filter(item -> JsonPath.read(item, "$.schedule") instanceof String) + .peek(this::expandOutputSchedule) + .toList(); + log.debug("ShorthandsExpansionHelper: Output schedules expanded: {}", expandedOutputSchedules); + + // ----- Expand Metric sensors ----- + List expandedSensors = asList(ctx + .read("$.spec.*.*.metrics.*[?(@.sensor)]", List.class)).stream() + .filter(item -> JsonPath.read(item, "$.sensor") instanceof String) + .peek(this::expandSensor) + .toList(); + log.debug("ShorthandsExpansionHelper: Sensors expanded: {}", expandedSensors); + } + + private void expandWindow(Object spec) { + log.debug("ShorthandsExpansionHelper.expandWindow: {}", spec); + String constraintStr = JsonPath.read(spec, "$.window").toString().trim(); + Matcher matcher = METRIC_WINDOW_PATTERN.matcher(constraintStr); + if (matcher.matches()) { + asMap(spec).put("window", Map.of( + "type", matcher.group(1), + "size", (matcher.groupCount()>2) + ? Map.of("value", matcher.group(2), "unit", matcher.group(3)) + : Map.of("value", matcher.group(2)) + )); + } else + throw createException("Invalid metric window shorthand expression: "+spec); + } + + private void expandWindowSize(Object spec) { + log.debug("ShorthandsExpansionHelper.expandWindowSize: {}", spec); + String constraintStr = JsonPath.read(spec, "$.size").toString().trim(); + Matcher matcher = METRIC_WINDOW_SIZE_PATTERN.matcher(constraintStr); + if (matcher.matches()) { + asMap(spec).put("size", (matcher.groupCount()>1) + ? Map.of("value", matcher.group(1), "unit", matcher.group(2)) + : Map.of("value", matcher.group(1)) + ); + } else + throw createException("Invalid metric window shorthand expression: "+spec); + } + + private void expandOutput(Object spec) { + log.debug("ShorthandsExpansionHelper.expandOutput: {}", spec); + String constraintStr = JsonPath.read(spec, "$.output").toString().trim(); + Matcher matcher = METRIC_OUTPUT_PATTERN.matcher(constraintStr); + if (matcher.matches()) { + asMap(spec).put("output", Map.of( + "type", matcher.group(1), + "schedule", Map.of( + "value", matcher.group(2), + "unit", matcher.group(3)) + )); + } else + throw createException("Invalid metric output shorthand expression: "+spec); + } + + private void expandOutputSchedule(Object spec) { + log.debug("ShorthandsExpansionHelper.expandOutputSchedule: {}", spec); + String constraintStr = JsonPath.read(spec, "$.schedule").toString().trim(); + Matcher matcher = METRIC_OUTPUT_SCHEDULE_PATTERN.matcher(constraintStr); + if (matcher.matches()) { + asMap(spec).put("schedule", Map.of( + "value", matcher.group(1), + "unit", matcher.group(2)) + ); + } else + throw createException("Invalid metric output shorthand expression: "+spec); + } + + private void expandSensor(Object spec) { + log.debug("ShorthandsExpansionHelper.expandSensor: {}", spec); + String constraintStr = JsonPath.read(spec, "$.sensor").toString().trim(); + Matcher matcher = METRIC_SENSOR_PATTERN.matcher(constraintStr); + if (matcher.matches()) { + asMap(spec).put("sensor", Map.of( + "type", matcher.group(1), + "config", Map.of("mapping", matcher.group(2)) + )); + } else + throw createException("Invalid metric sensor shorthand expression: "+spec); + } + + private void expandConstraint(Object spec) { + log.debug("ShorthandsExpansionHelper.expandConstraint: {}", spec); + String constraintStr = JsonPath.read(spec, "$.constraint").toString().trim(); + Matcher matcher = METRIC_CONSTRAINT_PATTERN.matcher(constraintStr); + if (matcher.matches()) { + String g1 = matcher.group(1); + String g2 = matcher.group(2); + String g3 = matcher.group(3); + + if (! isComparisonOperator(g2)) + throw createException("Invalid metric constraint shorthand expression in Requirement [Group 2 not a comparison operator]: "+spec); + + // Swap operands + if (isDouble(g1)) { + String tmp = g1; + g1 = g3; + g3 = tmp; + } + + if (StringUtils.isBlank(g1) || StringUtils.isBlank(g3)) + throw createException("Invalid metric constraint shorthand expression in Requirement [Group 1 or 3 is blank]: "+spec); + + String metricName = g1.trim(); + double threshold = Double.parseDouble(g3.trim()); + + Map constrMap = Map.of( + "type", "metric", + "metric", metricName, + "operator", g2.trim(), + "threshold", threshold + ); + + asMap(spec).put("constraint", constrMap); + } else + throw createException("Invalid metric constraint shorthand expression: "+spec); + } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleGenerator.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleGenerator.java new file mode 100644 index 0000000..0cb91d5 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleGenerator.java @@ -0,0 +1,960 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.generate; + +import eu.nebulous.ems.translate.NebulousEmsTranslator; +import gr.iccs.imu.ems.brokercep.cep.MathUtil; +import gr.iccs.imu.ems.translate.TranslationContext; +import gr.iccs.imu.ems.translate.model.*; +import eu.nebulous.ems.translate.NebulousEmsTranslatorProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring6.SpringTemplateEngine; +import org.thymeleaf.spring6.dialect.SpringStandardDialect; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.StringTemplateResolver; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RuleGenerator implements InitializingBean { + public final static String TRANSLATION_CONFIG = "translation_config"; + public final static String EPL_VALUE = "epl_value"; + public final static String EPL_FORMULA_TAG = "%EPL%>"; + + private final NebulousEmsTranslatorProperties properties; + private final RuleTemplateRegistry ruleTemplatesRegistry; + private SpringTemplateEngine templateEngine; + + // ======================================================================== + // Public API + // ======================================================================== + + @Override + public void afterPropertiesSet() { + initTemplateEngine(); + } + + public void generateRules(TranslationContext _TC) { + log.debug("RuleGenerator.ruleTemplates:\n{}", ruleTemplatesRegistry.getRuleTemplates()); + _generateRules(_TC); + _TC.getTopicConnections(); // force topicConnections population + _updateMonitors(_TC); + } + + // ======================================================================== + // Initialization methods + // ======================================================================== + + private void initTemplateEngine() { + StringTemplateResolver templateResolver = new StringTemplateResolver(); + templateResolver.setTemplateMode(TemplateMode.TEXT); + SpringStandardDialect dialect = new SpringStandardDialect(); + dialect.setEnableSpringELCompiler(true); + + SpringTemplateEngine engine = new SpringTemplateEngine(); + engine.setDialect(dialect); + engine.setEnableSpringELCompiler(true); + engine.setTemplateResolver(templateResolver); + + this.templateEngine = engine; + log.debug("RuleGenerator.initTemplateEngine(): Template engine initialized: {}", engine.getClass().getName()); + } + + // ======================================================================== + // Rule generation methods + // ======================================================================== + + private void _generateRules(TranslationContext _TC) { + // traverse DAG and generate EPL rules + log.debug("RuleGenerator.generateRules(): Traversing DAG..."); + _TC.getDAG().traverseDAG(node -> { + String grouping = node.getGrouping() != null ? node.getGrouping().toString() : null; + NamedElement elem = node.getElement(); + String elemName = elem != null ? getElemNameNormalized(elem) : null; + node.setTopicName(elemName); + Class elemClass = elem != null ? elem.getClass() : null; + log.debug("RuleGenerator.generateRules(): node: {}, grouping={}, elem-name={}, elem-class={}", node, grouping, elemName, elemClass); + + // Generate rules depending on the type of element + boolean providesTopic = true; + if (elem == null) { + // ignore this element + log.debug("RuleGenerator.generateRules(): IGNORE NODE. No element specified: node={}", node); + providesTopic = false; + } else + // Generate rules for Events and Event Patterns (and Metric Constraints) + /*if (elem instanceof BinaryEventPattern bep) { + log.debug("RuleGenerator.generateRules(): Found a Binary-Event-Pattern element: node={}, elem-name={}", node, elemName); + + // Get event pattern operator + String camelOp = bep.getOperator().toString(); + String ruleOp = camelToRule(MapType.OPERATOR, ElemType.BEP, camelOp); + + // Get event pattern composing events (just the names) + String leName = bep.getLeftEvent().getName(); + String reName = bep.getRightEvent().getName(); + log.debug("RuleGenerator.generateRules(): Binary-Event-Pattern: node={}, elem-name={}, operator={}->{}, left-event={}, right-event={}", node, elemName, camelOp, ruleOp, leName, reName); + +//XXX: ASK: Do we need 'lowOccurrenceBound', 'upperOccurrenceBound' and 'timer' ?? + + // Write rule for BEP + Context context = new Context(); + context.setVariable("operator", ruleOp); + context.setVariable("leftEvent", leName); + context.setVariable("rightEvent", reName); + _generateRule(_TC, "BEP-" + ruleOp, grouping, elem, context); + } else if (elem instanceof UnaryEventPattern uep) { + log.debug("RuleGenerator.generateRules(): Found a Unary-Event-Pattern element: node={}, elem-name={}", node, elemName); + + // Get event pattern operator + String camelOp = uep.getOperator().toString(); + String ruleOp = camelToRule(MapType.OPERATOR, ElemType.UEP, camelOp); + + // Get event pattern composing event (just the name) + String eventName = uep.getEvent().getName(); + log.debug("RuleGenerator.generateRules(): Unary-Event-Pattern: node={}, elem-name={}, operator={}->{}, event={}", node, elemName, camelOp, ruleOp, eventName); + +//XXX: ASK: Do we need 'occurrenceNum' and 'timer' ?? + + // Write rule for UEP + Context context = new Context(); + context.setVariable("operator", ruleOp); + context.setVariable("event", eventName); + _generateRule(_TC, "UEP-" + ruleOp, grouping, elem, context); + } else if (elem instanceof NonFunctionalEvent nfe) { + log.debug("RuleGenerator.generateRules(): Found a Non-Functional-Event element: node={}, elem-name={}", node, elemName); + + // Get event is-violation + boolean isViolation = nfe.isViolation(); + + // Get event's metric constraint (just the name) + MetricConstraint constr = nfe.getMetricConstraint(); + log.debug("RuleGenerator.generateRules(): Non-Functional-Event: node={}, elem-name={}, is-violation={}, metric-constraint={}", node, elemName, isViolation, constr.getName()); + + // Write rule for NFE + Context context = new Context(); + context.setVariable("metricConstraint", constr.getName()); + _generateRule(_TC, "NFE", grouping, elem, context); + } else*/ + + // Generate rules for Constraints + if (elem instanceof MetricConstraint) { + log.debug("RuleGenerator.generateRules(): Found a Metric-Constraint element: node={}, elem-name={}", node, elemName); + MetricConstraint constr = (MetricConstraint) elem; + + // Get metric constraint operator and threshold + String camelOp = constr.getComparisonOperator().toString(); + String ruleOp = camelToRule(MapType.OPERATOR, ElemType.CONSTR, camelOp); + double threshold = constr.getThreshold(); + + // Get constraint's metric context (just the name) + MetricContext mc = constr.getMetricContext(); + String mcName = getElemNameNormalized(mc); + log.debug("RuleGenerator.generateRules(): Metric-Constraint: node={}, elem-name={}, operator={}->{}, threshold={}, metric-context={}", + node, elemName, camelOp, ruleOp, threshold, mcName); + + // Require context topic in this level + _TC.requireGroupingTopicPair(grouping, mcName); + + // Write rule for CONSTR-MET + Context context = new Context(); + context.setVariable("metricContext", mcName); + context.setVariable("operator", ruleOp); + context.setVariable("threshold", threshold); + _generateRule(_TC, "CONSTR-MET", grouping, elem, context); + } else if (elem instanceof IfThenConstraint) { + log.debug("RuleGenerator.generateRules(): Found an If-Then-Constraint element: node={}, elem-name={}", node, elemName); + IfThenConstraint constr = (IfThenConstraint) elem; + + // Get constraint If, Then, Else child constraints + String ifConstr = getElemNameNormalized(constr.getIf()); + String thenConstr = getElemNameNormalized(constr.getThen()); + String elseConstr = constr.getElse()!=null ? getElemNameNormalized(constr.getElse()) : null; + + log.debug("RuleGenerator.generateRules(): If-Then-Constraint: node={}, elem-name={}, If={}, Then={}, Else={}", + node, elemName, ifConstr, thenConstr, elseConstr); + + // Require context topic in this level + _TC.requireGroupingTopicPair(grouping, getElemNameNormalized(constr)); + + // Write rule for CONSTR-IF-THEN + Context context = new Context(); + context.setVariable("ifConstraint", ifConstr); + context.setVariable("thenConstraint", thenConstr); + context.setVariable("elseConstraint", elseConstr); + _generateRule(_TC, "CONSTR-IF-THEN", grouping, elem, context); + } else if (elem instanceof MetricVariableConstraint) { + // Not used in EMS + log.debug("RuleGenerator.generateRules(): Found an Metric-Variable-Constraint element and ignoring it: node={}, elem-name={}", node, elemName); + } else if (elem instanceof LogicalConstraint) { + log.debug("RuleGenerator.generateRules(): Found a Logical-Constraint element: node={}, elem-name={}", node, elemName); + LogicalConstraint constr = (LogicalConstraint) elem; + + // Get logical constraint operator and component constraints + String camelOp = constr.getLogicalOperator().name(); + String ruleOp = camelToRule(MapType.OPERATOR, ElemType.CONSTR, camelOp); + List componentConstraintsNamesList = constr.getConstraints().stream() + .map(this::getElemNameNormalized).collect(Collectors.toList()); + + log.debug("RuleGenerator.generateRules(): Logical-Constraint: node={}, elem-name={}, operator={}->{}, component-constraints={}", node, elemName, camelOp, ruleOp, componentConstraintsNamesList); + + // Require context topic in this level + _TC.requireGroupingTopicPair(grouping, getElemNameNormalized(constr)); + + // Write rule for CONSTR-LOG + Context context = new Context(); + context.setVariable("operator", ruleOp); + context.setVariable("constraints", componentConstraintsNamesList); + _generateRule(_TC, "CONSTR-LOG", grouping, elem, context); + } else + + // Generate rules for Metrics Contexts + if (elem instanceof CompositeMetricContext cmc) { + log.debug("RuleGenerator.generateRules(): Found a Composite-Metric-Context element: node={}, elem-name={}", node, elemName); + + // Get composite metric context's metric parameters + CompositeMetric metric = (CompositeMetric) cmc.getMetric(); + String formula = metric.getFormula(); + List components = metric.getComponentMetrics(); + List componentNames = components.stream().map(this::getElemNameNormalized).collect(Collectors.toList()); + + boolean isAggregation = MathUtil.containsAggregator(formula); + + // Get composite metric context's window and schedule parameters + Window win = cmc.getWindow(); + String winClause = _generateWindowClause(win); + Schedule sched = cmc.getSchedule(); + String schedClause = _generateScheduleClause(sched, isAggregation ? "AGG" : null); + + // Get composite metric context's component or data parameters + String[] compAndDataName = getComponentAndDataName(cmc); + String compName = compAndDataName[0]; + String dataName = compAndDataName[1]; + + // Get composite metric context's composing metric contexts (just the names) + List composingCtxList = cmc.getComposingMetricContexts(); + List composingMetricNamesList = composingCtxList.stream() + //XXX:TODO: LOW-PRI: Improve by using formula rewrite in order to include component name too + //XXX:TODO: LOW-PRI: (e.g. 'mean([face-detection.latency_instance])' to 'mean( face_detection_latency__instance )' ) + .map(item -> StringUtils.defaultIfBlank( + StringUtils.substringAfterLast(item.getName(), "."), + item.getName())) + //.map(item -> getElemName(item.getMetric())) + .collect(Collectors.toList()); + List composingCtxNamesList = composingCtxList.stream().map(this::getElemNameNormalized).collect(Collectors.toList()); + + // Check that component metrics' names (from composite metric) and metric names from component contexts match + if (checkIfListsAreEqual(componentNames, composingCtxNamesList)) { + log.error("RuleGenerator.generateRules(): Component metrics of composite metric '{}' do not match to component contexts of Composite-Metric-Context '{}': component-metrics={}, component-context-metrics={}", + getElemNameNormalized(metric), getElemNameNormalized(cmc), componentNames, composingCtxNamesList); + throw new IllegalArgumentException(String.format("Component metrics of composite metric '%s' do not match to component contexts of Composite-Metric-Context: %s", metric.getName(), cmc.getName())); + } + + log.debug("RuleGenerator.generateRules(): Composite-Metric-Context: node={}, elem-name={}, metric={}, formula={}, components={}, win={}, sched={}, component={}, data={}, composing-metrics={}, composing-metric-contexts={}", + node, elemName, metric.getName(), formula, componentNames, winClause, schedClause, compName, dataName, composingMetricNamesList, composingCtxNamesList); + + // Require topics in this level + _TC.requireGroupingTopicPairs(grouping, composingCtxNamesList); + + // Select rule tag, depending on whether an Aggregator function is used in formula + // (a) COMP-CTX: when no Aggregator function is used in formula, (b) COMP-CTX-AGG: when an Aggregator function is used in formula + String ruleTag = "COMP-CTX"; + if (isAggregation) ruleTag = "AGG-COMP-CTX"; + log.debug("RuleGenerator.generateRules(): CMC-tag={}", ruleTag); + + // Write rule for CMC or CMC-AGG + Context context = new Context(); + context.setVariable("formula", formula); + context.setVariable("metric", getElemNameNormalized(metric)); + context.setVariable("components", composingMetricNamesList); + context.setVariable("contexts", composingCtxNamesList); + context.setVariable("windowClause", winClause); + context.setVariable("scheduleClause", schedClause); + _generateRule(_TC, ruleTag, grouping, elem, context); + } else if (elem instanceof RawMetricContext rmc) { + log.debug("RuleGenerator.generateRules(): Found a Raw-Metric-Context element: node={}, elem-name={}", node, elemName); + + // Get raw metric context's metric parameters + RawMetric metric = (RawMetric) rmc.getMetric(); + Sensor sensor = rmc.getSensor(); + String sensorName = sensor != null ? getElemNameNormalized(sensor) : null; + + // Get raw metric context's schedule parameters + Schedule sched = rmc.getSchedule(); + String schedClause = _generateScheduleClause(sched, null); + + // Get raw metric context's component or data parameters + String[] compAndDataName = getComponentAndDataName(rmc); + String compName = compAndDataName[0]; + String dataName = compAndDataName[1]; + + log.debug("RuleGenerator.generateRules(): Raw-Metric-Context: node={}, elem-name={}, metric={}, sensor={}, sched={}, component={}, data={}", + node, elemName, metric.getName(), sensorName, schedClause, compName, dataName); + + // Require topics in this level + _TC.requireGroupingTopicPair(grouping, getElemNameNormalized(rmc)); + + // Write rule for RMC + Context context = new Context(); + context.setVariable("metric", getElemNameNormalized(metric)); + context.setVariable("sensor", sensorName); + context.setVariable("scheduleClause", schedClause); + _generateRule(_TC, "RAW-CTX", grouping, elem, context); + } else + + // Generate rules for Metrics + /*if ((elem instanceof RawMetric || elem instanceof CompositeMetric) && _TC.getDAG().isTopLevelNode(node)) { + log.debug("RuleGenerator.generateRules(): Found a Top-Level Metric element: node={}, elem-name={}", node, elemName); + Metric m = (Metric) elem; + + // Get metric's context + Set mc = _TC.getM2MC().get(m); + List mcList = mc.stream().map(NamedElement::getName).collect(Collectors.toList()); + if (mc.size() != 1) { + log.error("RuleGenerator.generateRules(): Top-Level Metric has 0 or >1 contexts: metric={}, component-contexts={}", m.getName(), mcList); + throw new IllegalArgumentException(String.format("Top-Level Metric has 0 or >1 contexts: metric=%s, component-contexts=%s", m.getName(), mcList)); + } + MetricContext cmc = mc.stream().findFirst().get(); + + log.debug("RuleGenerator.generateRules(): Top-Level Metric: node={}, elem-name={}, context={}", + node, elemName, cmc.getName()); + + // Require topics in this level + _TC.requireGroupingTopicPair(grouping, cmc.getName()); + + // Write rule for MET + Context context = new Context(); + context.setVariable("context", cmc.getName()); + _generateRule(_TC, "TL-MET", grouping, elem, context); + + } else if (elem instanceof CompositeMetric) { + log.debug("RuleGenerator.generateRules(): Found a Composite-Metric element: node={}, elem-name={}", node, elemName); + providesTopic = false; + // Nothing to do here + } else if (elem instanceof RawMetric) { + log.debug("RuleGenerator.generateRules(): Found a Raw-Metric element: node={}, elem-name={}", node, elemName); + providesTopic = false; + // Nothing to do here + } else*/ + + // Generate rules for Metric Variables + if (elem instanceof BusyStatusMetricVariable) { + log.debug("RuleGenerator.generateRules(): Found a BUSY-STATUS metric variable element: node={}, elem-name={}", node, elemName); + MetricVariable mvar = (BusyStatusMetricVariable) elem; + Component comp = mvar.getComponent(); + String compName = comp != null ? comp.getName() : null; + + MetricContext busyStatusMetricContext = mvar.getMetricContext(); + String busyStatusMetricContextName = getElemNameNormalized(busyStatusMetricContext); + + log.debug("RuleGenerator.generateRules(): BUSY-STATUS metric variable: node={}, elem-name={}, component={}, metric-context={}", + node, elemName, compName, busyStatusMetricContextName); + + // Require topics in this level + _TC.requireGroupingTopicPair(grouping, busyStatusMetricContextName); + + // Write rule for BUSY-STATUS Metric Variable + Context context = new Context(); + context.setVariable("context", busyStatusMetricContextName); + _generateRule(_TC, "BUSY-STATUS-VAR", grouping, elem, context); + + } else + /*if (elem instanceof MetricVariable mvar) { + log.debug("RuleGenerator.generateRules(): Found a Metric-Variable element: node={}, elem-name={}", node, elemName); + boolean isCurrConfig = mvar.isCurrentConfiguration(); + boolean isOnNodeCand = mvar.isOnNodeCandidates(); + Component comp = mvar.getComponent(); + String compName = comp != null ? comp.getName() : null; + String formula = mvar.getFormula(); + List _componentMetrics = mvar.getComponentMetrics(); + List _componentMetricNames = _componentMetrics.stream().map(NamedElement::getName).collect(Collectors.toList()); + boolean _containsMetrics = _componentMetrics.size() > 0; + + log.debug("RuleGenerator.generateRules(): Metric-Variable: node={}, elem-name={}, is-current-config={}, is-on-node-candidates={}, component={}, formula={}, component-metrics={}, contains-metrics={}", + node, elemName, isCurrConfig, isOnNodeCand, compName, formula, _componentMetricNames, _containsMetrics); + + // Remove CP model variables from component metrics + List componentMetrics = new ArrayList<>(); + for (Metric m : _componentMetrics) { + if (m instanceof MetricVariable) { + if (CamelMetadataTool.isFromVariable(m.getObject(MetricVariableImpl.class))) { + log.debug("RuleGenerator.generateRules(): - CP model variable found and will be excluded from processing: {}", m.getName()); + continue; + } + } + componentMetrics.add(m); + } + List componentMetricNames = componentMetrics.stream().map(NamedElement::getName).collect(Collectors.toList()); + boolean containsMetrics = (componentMetrics.size() > 0); + + log.debug("RuleGenerator.generateRules(): Metric-Variable after removing CP model variables: node={}, elem-name={}, is-current-config={}, is-on-node-candidates={}, component={}, formula={}, component-metrics={}, contains-metrics={}", + node, elemName, isCurrConfig, isOnNodeCand, compName, formula, componentMetricNames, containsMetrics); + + // Select rule tag, depending on whether an Aggregator function is used in formula + // (a) VAR: when no Aggregator function is used in formula, (b) VAR-AGG: when an Aggregator function is used in formula + String ruleTag = "VAR"; + if (MathUtil.containsAggregator(formula)) ruleTag = "AGG-VAR"; + log.debug("RuleGenerator.generateRules(): VAR-tag={}", ruleTag); + + if (componentMetrics.size() > 0) { + // Write rule for VAR + List contexts = componentMetrics.stream().map(_TC::getMetricContextForMetric).filter(Objects::nonNull).toList(); + List metricNames = contexts.stream().map(item -> item.getMetric().getName()).collect(Collectors.toList()); + List contextNames = contexts.stream().map(NamedElement::getName).collect(Collectors.toList()); + log.debug("RuleGenerator.generateRules(): Metric-Variable: node={}, elem-name={}, component-metrics={}, component-metric-contexts={}", + node, elemName, metricNames, contextNames); + + // Check that component metrics' names (from metric variable) and metric names from component contexts match + if (! checkIfListsAreEqual(componentMetricNames, metricNames)) { + log.error("RuleGenerator.generateRules(): Component metrics of metric variable '{}' do not match to component contexts' metrics: component-metrics={}, component-context-metrics={}", mvar.getName(), componentMetricNames, metricNames); + throw new IllegalArgumentException(String.format("Component metrics of metric variable '%s' do not match to component contexts' metrics", mvar.getName())); + } + + if (contexts.size() > 0) { + // Require topics in this level + _TC.requireGroupingTopicPairs(grouping, contextNames); + + // Write rule for VAR + Context context = new Context(); + context.setVariable("formula", formula); + context.setVariable("variable", mvar.getName()); + context.setVariable("components", metricNames); + context.setVariable("contexts", contextNames); + _generateRule(_TC, ruleTag, grouping, elem, context); + } else { + // All component metrics for this metric variable do not have related metric contexts (i.e. the metric variable is MVV) + // No rules will be generated + log.debug("RuleGenerator.generateRules(): Metric-Variable has no metric contexts related to its component metrics. No rules will be generated: node={}, elem-name={}", node, elemName); + } + } else { + // No component metrics for this metric variable (i.e. it is a MVV) + // No rules will be generated + log.debug("RuleGenerator.generateRules(): Metric-Variable has no component metrics. No rules will be generated: node={}, elem-name={}", node, elemName); + } + } else*/ + + // Generate rules for Templates and Sensors + /*if (elem instanceof MetricTemplate) { + log.debug("RuleGenerator.generateRules(): Found a Metric-Template element: node={}, elem-name={}", node, elemName); + } else*/ + if (elem instanceof Sensor) { + log.debug("RuleGenerator.generateRules(): Found a Sensor element: node={}, elem-name={}", node, elemName); + } else + + // Generate rules for Optimisation Requirements and SLO's + /*if (elem instanceof OptimisationRequirement optr) { + log.debug("RuleGenerator.generateRules(): Found an Optimisation-Requirement element: node={}, elem-name={}", node, elemName); + MetricContext mc = optr.getMetricContext(); + MetricVariable mv = optr.getMetricVariable(); + + // Write rules for OPT-REQ + if (mc != null) { + Context context = new Context(); + context.setVariable("context", mc.getName()); + _generateRule(_TC, "OPT-REQ-CTX", grouping, elem, context); + } + if (mv != null) { + Context context = new Context(); + context.setVariable("variable", mv.getName()); + _generateRule(_TC, "OPT-REQ-VAR", grouping, elem, context); + } + } else*/ + if (elem instanceof ServiceLevelObjective slo) { + log.debug("RuleGenerator.generateRules(): Found a Service-Level-Objective element: node={}, elem-name={}", node, elemName); + Constraint constr = slo.getConstraint(); + + // Write rule for SLO + Context context = new Context(); + context.setVariable("constraint", getElemNameNormalized(constr)); + _generateRule(_TC, "SLO", grouping, elem, context); + } else + + { + log.debug("RuleGenerator.generateRules(): ERROR in NODE. Unsupported element type: node={}, elem-name={}, elem-class={}", node, elemName, elemClass); + providesTopic = false; + } + + // Add provided topic (i.e. this node generates the rule(s) that will create the events to be published in topic) + if (providesTopic) { + _TC.provideGroupingTopicPair(grouping, getElemNameNormalized(elem)); + } + }); + log.debug("RuleGenerator.generateRules(): Traversing DAG... done"); + } + + protected String getElemNameNormalized(NamedElement elem) { + return getElemNameNormalized(elem.getName()); + } + + protected String getElemNameNormalized(String name) { + return NebulousEmsTranslator.nameNormalization.apply(name); + } + + protected void _generateRule(TranslationContext _TC, String type, String grouping, NamedElement elem, Context context) { + String elemName = getElemNameNormalized(elem); + + // Check for sub-feature attribute 'translation_config.epl_value'. If it exists then the rule EPL statement is + // taken from its value (provided it is not null or blank, and it is a string value). + // Further rule generation actions are skipped. + log.trace("RuleGenerator._generateRule(): Checking if element is a feature: {} -- {}", elemName, elem.getClass()); + if (elem instanceof Feature) { + log.trace("RuleGenerator._generateRule(): Checking element for overriding translation sub-feature: {}", elemName); + String eplStmt = getEplValueFromSubfeatures((Feature) elem); + log.trace("RuleGenerator._generateRule(): Element overriding translation sub-feature: {} -- sub-feature: {}", elemName, eplStmt); + + if (StringUtils.isNotBlank(eplStmt)) { + log.debug("RuleGenerator._generateRule(): Element '{}' has '{}' set. EPL statement: {}", elemName, EPL_VALUE, eplStmt = eplStmt.trim()); + + // Store the generated rule in _TC + _TC.addGroupingRulePair(grouping, elemName, eplStmt); + log.debug("RuleGenerator._generateRule(): + Added EPL statement at Grouping {}: {}", grouping, eplStmt); + log.trace("RuleGenerator._generateRule(): Skipping further element rule processing: {}", elemName); + return; + } + } + + // Set selectMode based on 'formula's initial tag + String fml = Optional.ofNullable(context.getVariable("formula")).orElse("").toString(); + if (StringUtils.startsWithIgnoreCase(fml, EPL_FORMULA_TAG)) { + fml = fml.substring(EPL_FORMULA_TAG.length()); + context.setVariable("formula", fml); + context.setVariable("selectMode", "epl"); + } + + // Generate rule EPL statement using the configured templates + log.debug("RuleGenerator._generateRule(): Generating rules for Graph node: {} {} at Grouping: {}", type, elemName, grouping != null ? grouping : "-"); + String[] groupingLabels = {grouping, "__ANY__"}; + for (String label : groupingLabels) { + log.debug("RuleGenerator._generateRule(): Getting rule templates for: type={}, grouping={}", type, label); + for (String ruleTpl : ruleTemplatesRegistry.getTemplatesFor(type, label)) { + log.debug("RuleGenerator._generateRule(): Rule template for: type={}, grouping={} => {}", type, label, ruleTpl); + if (ruleTpl != null) { + // Use template engine to process the selected rule template + context.setVariable("outputStream", elemName); + String ruleStr = templateEngine.process(ruleTpl.trim(), context); + + // Store the generated rule in _TC + _TC.addGroupingRulePair(grouping, elemName, ruleStr); + log.debug("RuleGenerator._generateRule(): + Added rule at Grouping {}: {}", grouping, ruleStr); + } else { + log.warn("RuleGenerator._generateRule(): - No rule template found for '{}' at Grouping '{}': node={}", type, grouping, elemName); + } + } + } + } + + private static String getEplValueFromSubfeatures(Feature feature) { + List subFeaturesList = feature.getSubFeatures(); + if (subFeaturesList==null || subFeaturesList.size()==0) return null; + String result = feature.getSubFeatures().stream() + .peek(p->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... feature--BEFORE-FILTER: {}", p.getName())) + .filter(f -> TRANSLATION_CONFIG.equals(f.getName())) + .peek(p->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... feature--AFTER-FILTER: {}", p.getName())) + .map(Feature::getAttributes) + .filter(Objects::nonNull) + .filter(a->a.size()>0) + .peek(a->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... attribute--BEFORE-FLATMAP: {}", a)) + .flatMap(Collection::stream) + .peek(a->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... attribute--AFTER-FLATMAP: {}", a)) + .filter(a -> EPL_VALUE.equals(a.getName())) + .peek(a->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... attribute--AFTER-FILTER: {}", a)) + .map(Attribute::getValue) + .peek(o->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... value--BEFORE-FILTERS: {}", o)) + .filter(Objects::nonNull) + .peek(o->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... value--MID-FILTERS: {}", o)) + .filter(o -> o instanceof StringValue) + .peek(o->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... value--AFTER-FILTERS: {}", o)) + .map(o -> (StringValue) o) + .peek(o->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... string-value: {}", o)) + .map(StringValue::getValue) + .peek(o->log.trace("RuleGenerator.getEplViewFromSubfeatures(): ..... value: {}", o)) + .findFirst().orElse(null); + log.debug("RuleGenerator.getEplViewFromSubfeatures(): Processing={}, epl-view={}", feature.getName(), result); + return result; + } + + protected String _generateWindowClause(Window win) { + // No window specified + if (win==null) + return ".std:lastevent()"; + //return ""; + + // Sub-feature attribute 'translation_config.epl_value' value provides EPL statement + // and overrides Window processing + String eplStmt = getEplValueFromSubfeatures(win); + if (StringUtils.isNotBlank(eplStmt)) { + log.debug("RuleGenerator._generateWindowClause(): Window '{}' has 'epl_value' set. EPL value: {}", win.getName(), eplStmt = eplStmt.trim()); + return eplStmt; + } + + // Process Window settings for generating EPL statement + StringBuilder sb = new StringBuilder(); + + // Process 'groupwin' window group processings + if (win.getProcessings()!=null) { + win.getProcessings().stream() + .filter(p -> p.getProcessingType() == WindowProcessingType.GROUP) + .filter(this::groupingMustBeBeforeSizeOrTimeView) + .forEach(p -> _processGroupWindowProcessing(sb, p)); + } + + // Process 'time/size' window specifications + _processSizeOrTimeView(sb, win); + + // Process 'non-groupwin' window group processings + if (win.getProcessings()!=null) { + win.getProcessings().stream() + .filter(p -> p.getProcessingType() == WindowProcessingType.GROUP) + .filter(this::groupingMustBeAfterSizeOrTimeView) + .forEach(p -> _processGroupWindowProcessing(sb, p)); + } + + // Process window sort and rank processings + if (win.getProcessings()!=null) { + win.getProcessings().stream() + .filter(p -> p.getProcessingType() == WindowProcessingType.SORT || p.getProcessingType() == WindowProcessingType.RANK) + .forEach(p -> { + if (p.getProcessingType() == WindowProcessingType.SORT) + _processSortWindowProcessing(sb, p); + else if (p.getProcessingType() == WindowProcessingType.RANK) + _processRankWindowProcessing(sb, p); + }); + } + + String eplValue = sb.toString(); + log.debug("RuleGenerator._generateWindowClause(): Window '{}' generated EPL value: {}", win.getName(), eplValue); + return eplValue; + } + + private boolean groupingMustBeBeforeSizeOrTimeView(WindowProcessing windowProcessing) { + String eplView = getEplValueFromSubfeatures(windowProcessing); + log.debug("RuleGenerator.groupingMustBeBeforeSizeOrTimeView: processing={}, epl-value={}", windowProcessing.getName(), eplView); + boolean result = StringUtils.isBlank(eplView) || StringUtils.containsIgnoreCase(eplView, "groupwin"); + log.debug("RuleGenerator.groupingMustBeBeforeSizeOrTimeView: processing={}, result={}", windowProcessing.getName(), result); + return result; + } + + private boolean groupingMustBeAfterSizeOrTimeView(WindowProcessing windowProcessing) { + boolean result = !groupingMustBeBeforeSizeOrTimeView(windowProcessing); + log.debug("RuleGenerator.groupingMustBeAfterSizeOrTimeView(): processing={}, result={}", windowProcessing.getName(), result); + return result; + } + + private void _processSizeOrTimeView(StringBuilder sb, Window win) { + // WindowType: FIXED (Batch) or SLIDING + boolean isBatchWin = (WindowType.FIXED==win.getWindowType()); + boolean isSlidingWin = ! isBatchWin; + + // WindowSizeType: MEASUREMENTS_ONLY, TIME_ONLY, FIRST_MATCH, BOTH_MATCH + WindowSizeType winSizeType = win.getSizeType(); + boolean isFirstMatch = winSizeType==WindowSizeType.FIRST_MATCH; + boolean isBothMatch = winSizeType==WindowSizeType.BOTH_MATCH; + boolean isTimeOnly = winSizeType==WindowSizeType.TIME_ONLY; + boolean isEventsOnly = winSizeType==WindowSizeType.MEASUREMENTS_ONLY; + boolean isTimeAccum = winSizeType==WindowSizeType.TIME_ACCUM; + boolean isTimeOrder = winSizeType==WindowSizeType.TIME_ORDER; + + // Window size(s) + long winTimeSize = win.getTimeSize(); + long winMeasurementSize = win.getMeasurementSize(); + String winTimeUnit = win.getTimeUnit() != null ? win.getTimeUnit() : null; + + // Check for negative window sizes + if (winTimeSize<0 && ! isEventsOnly) { + log.warn("RuleGenerator._processSizeOrTimeView(): Time-based or First/Both-match window has NEGATIVE time. Skipping time window: window={}, type={}, window-time-size={}, window-time-unit={}", win.getName(), winSizeType, winTimeSize, winTimeUnit); + return; + } + if (winMeasurementSize<0 && (isEventsOnly || isFirstMatch || isBothMatch)) { + log.warn("RuleGenerator._processSizeOrTimeView(): Event-based or First/Both-match window has NEGATIVE length. Skipping event window: window={}, type={}, window-measurement-size={}", win.getName(), winSizeType, winTimeSize); + return; + } + + // Checks + if (! isEventsOnly) { + if (StringUtils.isBlank(winTimeUnit) || winTimeSize <= 0) { + log.error("RuleGenerator._processSizeOrTimeView(): ERROR: Invalid or missing window-time-size or window-time-unit: window={}, window-time-size={}, window-time-unit={}", win.getName(), winTimeSize, winTimeUnit); + throw new IllegalArgumentException(String.format("ERROR: Invalid or missing window-time-size or window-time-unit: window=%s, window-time-size=%d, window-time-unit=%s", win.getName(), winTimeSize, winTimeUnit)); + } + winTimeUnit = camelToRule(MapType.UNIT, ElemType.TIME, winTimeUnit); + } + + if (isFirstMatch || isBothMatch || isEventsOnly) { + if (winMeasurementSize <= 0) { + log.error("RuleGenerator._processSizeOrTimeView(): ERROR: Invalid window-measurement-size: window={}, window-measurement-size={}", win.getName(), winMeasurementSize); + throw new IllegalArgumentException(String.format("ERROR: Invalid window-measurement-size: window=%s, window-measurement-size=%s", win.getName(), winMeasurementSize)); + } + } + + if ((isTimeAccum || isTimeOrder) && isBatchWin) { + log.error("RuleGenerator._processSizeOrTimeView(): ERROR: 'Type-Accum' and 'Type-Order' windows cannot be Batch: window={}, window-type={}, window-size-type={}", win.getName(), win.getWindowType(), win.getSizeType()); + throw new IllegalArgumentException(String.format("ERROR: 'Type-Accum' and 'Type-Order' windows cannot be Batch: window=%s, window-type=%s, window-size-type=%s", win.getName(), win.getWindowType(), win.getSizeType())); + } + + // Generate the window length or time view + String s; + if (isFirstMatch) { + if (isSlidingWin) { // Sliding window + long millis = _winTimeToMillis(winTimeSize, winTimeUnit); + s = String.format(".win:expr(oldest_timestamp > newest_timestamp - %d and current_count <= %d)", millis, winMeasurementSize); +// s = String.format(".win:expr(oldest_event.includes(newest_event, %d %s) and current_count <= %d)%s", winTimeSize, winTimeUnit, winMeasurementSize, winViews); + } else { // Batch window + s = String.format(".win:time_length_batch(%d %s, %d)", winTimeSize, winTimeUnit, winMeasurementSize); + } + } else if (isBothMatch) { + long millis = _winTimeToMillis(winTimeSize, winTimeUnit); + s = String.format(".win:expr%s(oldest_timestamp > newest_timestamp - %d or current_count <= %d)", isBatchWin?"_batch":"", millis, winMeasurementSize); +// s = String.format(".win:expr%s(oldest_event.includes(newest_event, %d %s) or current_count <= %d)", isBatchWin?"_batch":"", winTimeSize, winTimeUnit, winMeasurementSize); + } else if (isTimeOnly) { + s = String.format(".win:time%s(%d %s)", isBatchWin?"_batch":"", winTimeSize, winTimeUnit); + } else if (isEventsOnly) { + s = String.format(".win:length%s(%d)", isBatchWin?"_batch":"", winMeasurementSize); + } else if (isTimeAccum) { + s = String.format(".win:time_accum(%d)", winMeasurementSize); + } else if (isTimeOrder) { + s = String.format(".ext:time_order(timestamp, %d)", winMeasurementSize); + } else { + log.error("RuleGenerator._processSizeOrTimeView(): ERROR: Invalid or Unsupported window-size-type: window={}, window-size-type={}", win.getName(), winSizeType); + throw new IllegalArgumentException(String.format("ERROR: Invalid or Unsupported window-size-type: window=%s, window-size-type=%s", win.getName(), winSizeType)); + } + + sb.append(s); + } + + private void _processGroupWindowProcessing(StringBuilder sb, WindowProcessing p) { + _processWindowProcessingCriteria(sb, p, p.getGroupingCriteria(), ".std:groupwin(", null, false); + } + + private void _processSortWindowProcessing(StringBuilder sb, WindowProcessing p) { + _processWindowProcessingCriteria(sb, p, p.getRankingCriteria(), ".ext:sort("+Integer.MAX_VALUE+", ", null, true); + } + + private void _processRankWindowProcessing(StringBuilder sb, WindowProcessing p) { + _processWindowProcessingCriteria(sb, p, p.getRankingCriteria(), ".ext:rank(", Integer.MAX_VALUE+")", true); + } + + private void _processWindowProcessingCriteria(StringBuilder sb, WindowProcessing p, List criteriaList, String openView, String closeView, boolean allowTimestampType) { + // Get view from translation overriding sub-feature + String view = getEplValueFromSubfeatures(p); + if (StringUtils.isNotBlank(view)) { + sb.append(view); + return; + } + + // Default view processing + if (criteriaList!=null && criteriaList.size()>0) { + if (StringUtils.isBlank(view)) { + view = openView; + } else + if (! view.trim().startsWith(".") && ! view.trim().startsWith("#")) { + view = view.contains(":") ? "."+view.trim() : "#"+view.trim(); + } else { + view = view.trim(); + } + + // Add view opening + sb.append(view); + if (!view.trim().endsWith("(") && !view.trim().endsWith(",")) sb.append("("); + + final boolean[] first = {true}; + criteriaList.forEach(c->{ + if (first[0]) first[0] = false; else sb.append(", "); + log.debug("RuleGenerator._processWindowProcessingCriteria(): {} processing criterion: processing={}, criterion={}, type={}, custom={}, metric={}", + p.getProcessingType(), p.getName(), c.getName(), c.getType(), c.getCustom(), c.getMetric()); + if (CriterionType.CUSTOM==c.getType()) { + if (StringUtils.isNotBlank(c.getCustom())) { + sb.append(c.getCustom().trim()); + } else { + log.error("RuleGenerator._processWindowProcessingCriteria(): CUSTOM group processing Criterion type must provide 'custom' property: {}", c.getName()); + throw new IllegalArgumentException("CUSTOM group processing Criterion type must provide 'custom' property: " + c.getName()); + } + } else + if (CriterionType.TIMESTAMP==c.getType()) { + if (allowTimestampType) { + sb.append("timestamp"); + } else { + log.error("RuleGenerator._processWindowProcessingCriteria(): TIMESTAMP processing Criterion type MUST NOT be used for grouping: {}", c.getName()); + throw new IllegalArgumentException("TIMESTAMP processing Criterion type MUST NOT be used for grouping: " + c.getName()); + } + } else + if (CriterionType.INSTANCE==c.getType()) { + sb.append("prop(*, 'instance')"); + } else + if (CriterionType.HOST==c.getType()) { + sb.append("prop(*, 'host')"); + } else + if (CriterionType.ZONE==c.getType()) { + sb.append("prop(*, 'zone')"); + } else + if (CriterionType.REGION==c.getType()) { + sb.append("prop(*, 'region')"); + } else + if (CriterionType.CLOUD==c.getType()) { + sb.append("prop(*, 'cloud')"); + } else + { + log.error("RuleGenerator._processWindowProcessingCriteria(): Unsupported Processing Criterion type: {}", c.getType()); + throw new IllegalArgumentException("Unsupported Processing Criterion type: " + c.getType()); + } + }); + + // Add view close + if (StringUtils.isNotBlank(closeView)) sb.append(closeView); else sb.append(")"); + + } else { + log.warn("RuleGenerator._processWindowProcessingCriteria: {} window processing with NO grouping criteria. Processing is ignored: {}", p.getProcessingType(), p.getName()); + } + } + + private long _winTimeToMillis(long time, String unit) { + return switch (unit.toLowerCase()) { + case "msec", "millisecond", "milliseconds" -> time; + case "sec", "second", "seconds" -> TimeUnit.MILLISECONDS.convert(time, TimeUnit.SECONDS); + case "min", "minute", "minutes" -> TimeUnit.MILLISECONDS.convert(time, TimeUnit.MINUTES); + case "hour", "hours" -> TimeUnit.MILLISECONDS.convert(time, TimeUnit.HOURS); + case "day", "days" -> TimeUnit.MILLISECONDS.convert(time, TimeUnit.DAYS); + case "week", "weeks" -> TimeUnit.MILLISECONDS.convert(7 * time, TimeUnit.DAYS); + case "month", "months" -> { + log.warn("RuleGenerator._winTimeToMillis: NOTE: 'Months' time unit equals to 30 days!"); + yield TimeUnit.MILLISECONDS.convert(30 * time, TimeUnit.DAYS); + } + case "year", "years" -> { + log.debug("RuleGenerator._winTimeToMillis: NOTE: 'Years' time unit equals to 365 days!"); + yield TimeUnit.MILLISECONDS.convert(365 * time, TimeUnit.DAYS); + } + default -> throw new RuntimeException("Unsupported time unit: \"" + unit + "\""); + }; + } + + protected String _generateScheduleClause(Schedule sched, String selector) { + if (sched == null) return ""; + + int schedRepetitions = sched.getRepetitions(); + long schedInterval = sched.getInterval(); + if (schedRepetitions <= 0 && schedInterval <= 0) return ""; + + if (schedRepetitions > 0 && schedInterval > 0) { + log.error("RuleGenerator._generateScheduleClause(): ERROR: Schedule has both 'repetitions' and 'interval' properties non-zero: repetitions={}, interval={}", schedRepetitions, schedInterval); + throw new IllegalArgumentException(String.format("ERROR: Schedule has both 'repetitions' and 'interval' properties non-zero: repetitions=%s, interval=%s", schedRepetitions, schedInterval)); + } + + long schedPeriod; + String schedUnit; + if (schedInterval > 0) { + schedPeriod = schedInterval; + schedUnit = sched.getTimeUnit(); + schedUnit = camelToRule(MapType.UNIT, ElemType.TIME, schedUnit); + } else { + schedPeriod = schedRepetitions; + schedUnit = "EVENTS"; + } + + if (StringUtils.isBlank(selector)) selector = "__ANY__"; + String schedTpl = ruleTemplatesRegistry.getTemplatesFor("SCHEDULE", selector).stream().findFirst().orElse(null); + log.trace("RuleGenerator._generateScheduleClause(): schedule-tpl: {}", schedTpl); + if (schedTpl != null) { + // Use template engine to process the selected schedule template + Context context = new Context(); + context.setVariable("type", sched.getType().toString()); + context.setVariable("period", schedPeriod); + context.setVariable("unit", schedUnit); + String schedStr = templateEngine.process(schedTpl.trim(), context); + log.debug("RuleGenerator._generateScheduleClause(): schedule-clause: {}", schedStr); + return schedStr; + } else { + return String.format("\nOUTPUT LAST EVERY %d %s", schedPeriod, schedUnit); + } + } + + // ======================================================================== + // Monitor update methods + // ======================================================================== + + private void _updateMonitors(TranslationContext _TC) { + // Normalize entries of _TC.MONS (names of sensors, which coincides with monitor metrics) + Set newSensorNames = _TC.getMONS().stream().map(this::getElemNameNormalized).collect(Collectors.toSet()); + _TC.getMONS().clear(); + _TC.getMONS().addAll(newSensorNames); + + // Normalize entries of _TC.MON (names in monitors, i.e. metric, and sensor name) + _TC.getMON().forEach(mon -> { + String newMetric = getElemNameNormalized(mon.getMetric()); + String newSensorName = getElemNameNormalized(mon.getSensor().getName()); + mon.setMetric(newMetric); + mon.getSensor().setName(newSensorName); + }); + } + + // ======================================================================== + // Helper methods + // ======================================================================== + + protected String camelToRule(MapType mapType, ElemType elemType, String camelStr) { + if (MapType.OPERATOR == mapType && ElemType.CONSTR == elemType) { + if ("GREATER_THAN".equalsIgnoreCase(camelStr)) return ">"; + if ("GREATER_EQUAL_THAN".equalsIgnoreCase(camelStr)) return ">="; + if ("LESS_THAN".equalsIgnoreCase(camelStr)) return "<"; + if ("LESS_EQUAL_THAN".equalsIgnoreCase(camelStr)) return "<="; + if ("EQUAL".equalsIgnoreCase(camelStr)) return "="; + if ("NOT_EQUAL".equalsIgnoreCase(camelStr)) return "<>"; + if ("AND".equalsIgnoreCase(camelStr)) return "AND"; + if ("OR".equalsIgnoreCase(camelStr)) return "OR"; + //XXX: EPL does not support XOR event patterns: + // if ("XOR".equalsIgnoreCase(camelStr)) return "XOR"; + throw new IllegalArgumentException(String.format("Illegal argument in 'camelStr': MapType=%s, ElemType=%s, camel-str=%s", mapType, elemType, camelStr)); + } + return camelStr.toUpperCase().trim(); + } + + protected boolean checkIfListsAreEqual(List list1, List list2) { + if (list1 == null && list2 == null) return true; + else if (list1 != null && list2 == null || list1 == null || list1.size() != list2.size()) + return false; + //else + List sorted1 = new ArrayList<>(list1); + List sorted2 = new ArrayList<>(list2); + java.util.Collections.sort(sorted1); + java.util.Collections.sort(sorted2); + return sorted1.equals(sorted2); + } + + protected String[] getComponentAndDataName(MetricContext mc) { + String compName = null; + String dataName = null; + if (mc != null) { + ObjectContext objCtx = mc.getObjectContext(); + if (objCtx != null) { + Component comp = objCtx.getComponent(); + Data data = objCtx.getData(); + compName = comp != null ? comp.getName() : null; + dataName = data != null ? data.getName() : null; + } + } + String[] result = new String[2]; + result[0] = compName; + result[1] = dataName; + return result; + } + + // ======================================================================== + // Helper classes and enums + // ======================================================================== + + protected enum MapType { OPERATOR, UNIT } + + protected enum ElemType { BEP, UEP, NFE, FE, CONSTR, CMC, RCM, CM, RM, MT, SENSOR, TIME, EVENT } +} \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleTemplateRegistry.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleTemplateRegistry.java new file mode 100644 index 0000000..63d0225 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/generate/RuleTemplateRegistry.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.generate; + +import gr.iccs.imu.ems.util.EmsConstant; +import lombok.Data; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.stereotype.Service; +import org.springframework.util.StreamUtils; +import org.yaml.snakeyaml.Yaml; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@Data +@Service +public class RuleTemplateRegistry implements InitializingBean { + @ToString.Exclude + private final ResourceLoader resourceLoader; + + private String language; + private Map>> ruleTemplates; + + @Override + public void afterPropertiesSet() throws IOException { + loadRuleTemplates(resourceLoader); + log.debug("RuleTemplateProperties: {}", this); + } + + private void loadRuleTemplates(ResourceLoader resourceLoader) throws IOException { + // Load templates from resource + Resource resource = resourceLoader.getResource("classpath:rule-templates.yml"); + String content = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8); + + // Parse resource contents (YAML) into a Map + Yaml yaml = new Yaml(); + Map result = yaml.loadAs(content, Map.class); + result = (Map) result.get(EmsConstant.EMS_PROPERTIES_PREFIX + "translator.generator"); + + // Update variables + language = result.get("language").toString(); + ruleTemplates = (Map>>)result.get("rule-templates"); + } + + public List getTemplatesFor(String type, String grouping) { + log.trace("RuleTemplateProperties.getTemplatesFor: type={}, grouping={}", type, grouping); + List list = Optional.ofNullable(ruleTemplates.get(type)).map(groupings -> groupings.get(grouping)).orElse(Collections.emptyList()); + log.trace("RuleTemplateProperties.getTemplatesFor: results={}", list); + return list; + } +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/NetdataPostProcessorPlugin.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/NetdataPostProcessorPlugin.java new file mode 100644 index 0000000..f6d4921 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/NetdataPostProcessorPlugin.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.plugins; + +import gr.iccs.imu.ems.translate.model.Sensor; +import gr.iccs.imu.ems.util.EmsConstant; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +@Slf4j +@Service +public class NetdataPostProcessorPlugin implements SensorPostProcessorPlugin { + public final static String NETDATA_TYPE = "netdata"; + + @Override + public List getSupportedTypes() { + return List.of(NETDATA_TYPE); + } + + @Override + public void postProcessSensor(Sensor sensor, String sensorType, Map sensorSpec) { + if (NETDATA_TYPE.equalsIgnoreCase(sensorType)) { + Object o = sensor.getConfiguration().get("mapping"); + if (o instanceof String s && StringUtils.isNotBlank(s)) { + if (! sensor.getConfiguration().containsKey(EmsConstant.COLLECTOR_DESTINATION_ALIASES)) { + sensor.getConfiguration().put(EmsConstant.COLLECTOR_DESTINATION_ALIASES, s.trim()); + } + } + } + } +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/SensorPostProcessorPlugin.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/SensorPostProcessorPlugin.java new file mode 100644 index 0000000..46d23db --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/plugins/SensorPostProcessorPlugin.java @@ -0,0 +1,15 @@ +package eu.nebulous.ems.translate.plugins; + +import gr.iccs.imu.ems.translate.model.Sensor; +import gr.iccs.imu.ems.util.Plugin; + +import java.util.List; +import java.util.Map; + +/** + * Sensor Post-Processor plugin (used ONLY in EMS-Nebulous) + */ +public interface SensorPostProcessorPlugin extends Plugin { + List getSupportedTypes(); + void postProcessSensor(Sensor sensor, String sensorType, Map sensorSpec); +} diff --git a/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/transform/GraphTransformer.java b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/transform/GraphTransformer.java new file mode 100644 index 0000000..150e527 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/translate/transform/GraphTransformer.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2023-2025 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.nebulous.ems.translate.transform; + +import gr.iccs.imu.ems.translate.Grouping; +import gr.iccs.imu.ems.translate.dag.DAG; +import gr.iccs.imu.ems.translate.dag.DAGNode; +import gr.iccs.imu.ems.translate.model.Metric; +import gr.iccs.imu.ems.translate.model.MetricContext; +import gr.iccs.imu.ems.translate.model.MetricVariable; +import gr.iccs.imu.ems.translate.model.NamedElement; +import eu.nebulous.ems.translate.NebulousEmsTranslatorProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Set; + +@Slf4j +@Service +@RequiredArgsConstructor +public class GraphTransformer { + private final NebulousEmsTranslatorProperties properties; + + public void transformGraph(DAG dag) { + log.debug("GraphTransformer.transformGraph(): Transforming DAG..."); + if (properties.isPruneMvv()) { + removeMVV(dag, dag.getRootNode()); + } else { + log.debug("GraphTransformer.transformGraph(): MVV pruning from DAG is disabled"); + } + + if (properties.isAddTopLevelMetrics()) { + addTopLevelMetrics(dag); + } else { + log.debug("GraphTransformer.transformGraph(): Adding Metric for Top-Level Metric Contexts in DAG is disabled"); + } + + log.debug("GraphTransformer.transformGraph(): Transforming DAG... done"); + } + + // Branch pruning when all nodes in branch are MVVs or Metric Variables calculated using exclusively MVVs or other Metric Variables calculated using MVVs + private void removeMVV(DAG dag, DAGNode node) { + log.debug("GraphTransformer.removeMVV(): Checking node {}...", node); + + // first process children (i.e. first prune child MVV's) + Set children = dag.getNodeChildren(node); + log.debug("GraphTransformer.removeMVV(): Initial node children: node={}, children: {}", node, children); + if (children != null) { + for (DAGNode child : children) { + removeMVV(dag, child); + } + } + + children = dag.getNodeChildren(node); + log.debug("GraphTransformer.removeMVV(): Node children after pruning: node={}, children: {}", node, children); + + // check if this node is MVV (i.e. has no child MVV's and is Metric Variable) + if (node.getElement() != null) { + if (children==null || children.isEmpty()) { + if (node.getElement() instanceof MetricVariable) { + // remove from DAG + log.debug("GraphTransformer.removeMVV(): Node is MVV: node={}", node); + dag.removeNode(node.getElement()); + log.debug("GraphTransformer.removeMVV(): MVV node pruned: node={}", node); + return; + } + } + } + // i.e. 'node' is not Metric variable or it has children that are not MVVs + log.debug("GraphTransformer.removeMVV(): Node is not MVV: node={}", node); + } + + private void addTopLevelMetrics(DAG dag) { + log.debug("GraphTransformer.addTopLevelMetrics(): Adding parent metric to all Top-Level metric contexts..."); + + dag.getTopLevelNodes().forEach(tln -> { + NamedElement elem = tln.getElement(); + log.debug("GraphTransformer.addTopLevelMetrics(): - Top-Level node: {}", tln.getName()); + if (elem!=null) { + log.debug("GraphTransformer.addTopLevelMetrics(): - Top-Level node element: {} ({})", elem.getName(), elem.getClass().getName()); + if (elem instanceof MetricContext mc) { + Metric m = mc.getMetric(); + log.debug("GraphTransformer.addTopLevelMetrics(): - Top-Level node element is Metric Context: context={}, metric={}", mc.getName(), m.getName()); + + // add Metric as metric context's parent + dag.addTopLevelNode(m).setGrouping(Grouping.GLOBAL); + dag.addNode(m, mc); + dag.removeEdge(dag.getRootNode(), tln); + log.debug("GraphTransformer.addTopLevelMetrics(): - New Top-Level node added for metric {}, instead of metric context {}", m.getName(), mc.getName()); + } else { + log.debug("GraphTransformer.addTopLevelMetrics(): - Ignoring element: {}", elem.getName()); + } + } else { + log.debug("GraphTransformer.addTopLevelMetrics(): - Top-Level node with 'null' element encountered: {}", tln.getName()); + } + }); + + log.debug("GraphTransformer.addTopLevelMetrics(): Adding parent metric to all Top-Level metric contexts...ok"); + } +} diff --git a/nebulous/ems-nebulous/src/main/resources/metric-model-schematron.xml b/nebulous/ems-nebulous/src/main/resources/metric-model-schematron.xml new file mode 100644 index 0000000..4a918b7 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/resources/metric-model-schematron.xml @@ -0,0 +1,16 @@ + + + + + + + + + Element 'apiVersion' must be present + + + Element 'apiVersion' value must be 'nebulous/v1' + + + + \ No newline at end of file diff --git a/nebulous/ems-nebulous/src/main/resources/rule-templates.yml b/nebulous/ems-nebulous/src/main/resources/rule-templates.yml new file mode 100644 index 0000000..8ec60f7 --- /dev/null +++ b/nebulous/ems-nebulous/src/main/resources/rule-templates.yml @@ -0,0 +1,236 @@ +# +# Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr) +# +# This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless +# Esper library is used, in which case it is subject to the terms of General Public License v2.0. +# If a copy of the MPL was not distributed with this file, you can obtain one at +# https://www.mozilla.org/en-US/MPL/2.0/ +# + +# EPL Rule templates per Element-Type and Monitoring-Grouping + +translator.generator: + language: EPL + rule-templates: + # SCHEDULE (i.e. OUTPUT) CLAUSE + SCHEDULE: + __ANY__: + - | + OUTPUT [(${type})] EVERY [(${period})] [(${unit})] + AGG: + - | + OUTPUT SNAPSHOT EVERY [(${period})] [(${unit})] + # Binary-Event-Pattern templates + BEP-AND: + GLOBAL: + - | + /* BEP-AND-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT le.* FROM [(${leftEvent})].std:lastevent() AS le, [(${rightEvent})].std:lastevent() AS re + BEP-OR: + GLOBAL: +#XXX: TEST: + - | + /* BEP-OR-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT CASE WHEN le IS NULL THEN re ELSE le END AS evt FROM PATTERN [ EVERY ( le=[(${leftEvent})] OR re=[(${rightEvent})] ) ] + BEP-XOR: +#XXX: XOR is NOT SUPPORTED: IS IT EQUIVALENT TO OR?? + GLOBAL: +#XXX: TEST: + - | + /* BEP-XOR-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT CASE WHEN le IS NULL THEN re ELSE le END AS evt FROM PATTERN [ EVERY ( le=[(${leftEvent})] OR re=[(${rightEvent})] ) ] + BEP-PRECEDES: + GLOBAL: +#XXX: TEST: + - | + /* BEP-PRECEDES-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT le.* FROM PATTERN [ EVERY ( le=[(${leftEvent})] -> re=[(${rightEvent})] ) ] + BEP-REPEAT_UNTIL: + GLOBAL: +#XXX: TEST: + - | + /* BEP-REPEAT_UNTIL-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT re.* FROM PATTERN [ EVERY [ le=[(${leftEvent})] UNTIL re=[(${rightEvent})] ] ] WHERE le IS NOT NULL + + # Unary-Event-Pattern templates + UEP-EVERY: +#XXX: WHAT'S THE MEANING OF THIS OPERATOR?? ...IF STANDALONE?? + GLOBAL: + - | + /* UEP-EVERY-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT ue.* FROM PATTERN [ EVERY ue=[(${unaryEvent})] ] + UEP-NOT: +#XXX: WHAT'S THE MEANING OF THIS OPERATOR?? ...IF STANDALONE?? + GLOBAL: + - | + /* UEP-NOT-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT ue.* FROM PATTERN [ NOT ue=[(${unaryEvent})] ] + UEP-REPEAT: + GLOBAL: +#XXX: TEST: + - | + /* UEP-REPEAT-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT ue[0].* FROM PATTERN [ [[(${occurrenceNum})]] ue=[(${unaryEvent})] ] + UEP-WHEN: +#XXX: WHAT'S THE MEANING OF THIS OPERATOR?? ...IF STANDALONE?? + GLOBAL: + - | + /* UEP-WHEN-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT ue.* FROM [(${leftEvent})].std:lastevent() AS ue + + # Non-Functional-Event templates + NFE: + GLOBAL: + - | + /* NFE-GLOBAL */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${metricConstraint})].std:lastevent() + + # Metric-Constraint templates + CONSTR-MET: + __ANY__: + - | + /* CONSTR-MET-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${metricContext})] HAVING [(${metricContext})].metricValue [(${operator})] [(${threshold})] + + # Logical-Constraint templates + CONSTR-LOG: + __ANY__: + - | + /* CONSTR-LOG-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT 1 AS metricValue, 3 AS level, current_timestamp AS timestamp + FROM PATTERN [ EVERY ( [# th:each="con,iterStat : ${constraints}" th:text="!${iterStat.last} ? ${con} + ' '+${operator}+' ' : ${con}"] [/] ) ] + + # If-Then-Constraint templates + CONSTR-IF-THEN: + __ANY__: +#XXX: TEST: + - | + /* CONSTR-IF-THEN-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT 1 AS metricValue, 3 AS level, current_timestamp AS timestamp + FROM PATTERN [ EVERY ( [(${ifConstraint})] AND [(${thenConstraint})] [# th:if="${elseConstraint != null}" th:text="'OR NOT ( ' + ${ifConstraint} + ' ) AND ' + ${elseConstraint}"] [/] ) ] + + # Context templates + COMP-CTX: + __ANY__: + - | + /* COMP-CTX-any */ /*INSERT INTO [(${outputStream})]*/ [# th:switch="${selectMode}"] [# th:case="'epl'"] + SELECT [(${formula})] [/] [# th:case="*"] + SELECT EVAL( '[(${formula})]', '[# th:each="ctx,iterStat : ${components}" th:text="!${iterStat.last} ? ${ctx} + ',' : ${ctx}"] [/]', [# th:each="ctx,iterStat : ${contexts}" th:text="!${iterStat.last} ? ${ctx} + ', ' : ${ctx}"] [/] ) AS metricValue, + 3 AS level, + current_timestamp AS timestamp [/] [/] + FROM [# th:each="ctx,iterStat : ${contexts}" th:utext="!${iterStat.last} ? ${ctx}+${windowClause}+' AS '+${ctx} + ', ' : ${ctx}+${windowClause}+' AS '+${ctx}"] [/] + [(${scheduleClause})] + + AGG-COMP-CTX: + __ANY__: + - | + /* COMP-CTX-AGG-any */ /*INSERT INTO [(${outputStream})]*/ [# th:switch="${selectMode}"] [# th:case="'epl'"] + SELECT [(${formula})] [/] [# th:case="*"] + SELECT EVALAGG( '[(${formula})]', '[# th:each="ctx,iterStat : ${components}" th:text="!${iterStat.last} ? ${ctx} + ',' : ${ctx}"] [/]', [# th:each="ctx,iterStat : ${contexts}" th:text="!${iterStat.last} ? ${ctx} + ', ' : ${ctx}"] [/] ) AS metricValue, + 3 AS level, + current_timestamp AS timestamp [/] [/] + FROM [# th:each="ctx,iterStat : ${contexts}" th:utext="!${iterStat.last} ? ${ctx}+${windowClause}+' AS '+${ctx} + ', ' : ${ctx}+${windowClause}+' AS '+${ctx}"] [/] + [(${scheduleClause})] + + RAW-CTX: + PER_INSTANCE: + - | + /* RAW-CTX-PER_INSTANCE */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${sensor})] [(${scheduleClause})] + + # Metric templates + TL-MET: + __ANY__: + - | + /* MET-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${context})] + + # Metric Variable templates + VAR: + __ANY__: + - | + /* VAR-any */ /*INSERT INTO [(${outputStream})]*/ [# th:switch="${selectMode}"] [# th:case="'epl'"] + SELECT [(${formula})] [/] [# th:case="*"] + SELECT EVAL( '[(${formula})]', '[# th:each="ctx,iterStat : ${components}" th:text="!${iterStat.last} ? ${ctx} + ',' : ${ctx}"] [/]', [# th:each="ctx,iterStat : ${contexts}" th:text="!${iterStat.last} ? ${ctx} + ', ' : ${ctx}"] [/] ) AS metricValue, + 3 AS level, + current_timestamp AS timestamp [/] [/] + FROM [# th:each="ctx,iterStat : ${contexts}" th:text="!${iterStat.last} ? ${ctx}+' AS '+${ctx} + ', ' : ${ctx}+' AS '+${ctx}"] [/] + + AGG-VAR: + __ANY__: + - | + /* VAR-AGG-any */ /*INSERT INTO [(${outputStream})]*/ [# th:switch="${selectMode}"] [# th:case="'epl'"] + SELECT [(${formula})] [/] [# th:case="*"] + SELECT EVALAGG( '[(${formula})]', '[# th:each="ctx,iterStat : ${components}" th:text="!${iterStat.last} ? ${ctx} + ',' : ${ctx}"] [/]', [# th:each="ctx,iterStat : ${contexts}" th:text="!${iterStat.last} ? ${ctx} + ', ' : ${ctx}"] [/] ) AS metricValue, + 3 AS level, + current_timestamp AS timestamp [/] [/] + FROM [# th:each="ctx,iterStat : ${contexts}" th:text="!${iterStat.last} ? ${ctx}+' AS '+${ctx} + ', ' : ${ctx}+' AS '+${ctx}"] [/] + + BUSY-STATUS-VAR: + __ANY__: + - | + /* BUSY-STATUS-VAR-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${context})] + + # Optimisation-Requirement templates + OPT-REQ-CTX: + __ANY__: + - | + /* OPT-REQ-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${context})] + + OPT-REQ-VAR: + __ANY__: + - | + /* OPT-REQ-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${variable})] + + # SLO templates + SLO: + __ANY__: + - | + /* SLO-any */ /*INSERT INTO [(${outputStream})]*/ + SELECT * FROM [(${constraint})] + +#XXX:DEL:...remove next rule + XXX-extra-rule-templates: + BEP-AND: + GLOBAL: + - | + /* BEP-AND-GLOBAL : ALTERNATIVE */ /*INSERT INTO [(${outputStream})]*/ + SELECT le.* FROM PATTERN [ EVERY (le=[(${leftEvent})] AND re=[(${rightEvent})]) ] + RAW-CTX: + PER_INSTANCE: + - | + /* RAW-CTX-PER_INSTANCE */ + INSERT INTO TEST_STREAM + SELECT EVAL('-1*CPUMetric+CPUMetric_2+CPUMetric_3', '[(${metric})],[(${metric})]_2,[(${metric})]_3', [(${metric})], [(${metric})]_2, [(${metric})]_3) AS metricValue, + 1 AS level, + current_timestamp AS timestamp + FROM [(${metric})] as [(${metric})], [(${metric})] as [(${metric})]_2, [(${metric})] as [(${metric})]_3[(${scheduleClause})] + + FE: + PER_INSTANCE: + - | + /* XXX: TODO: FE-PER_INSTANCE */ + .......... Functional Event + CONSTR-IF-THEN: + PER_INSTANCE: + - | + /* XXX: TODO: CONSTR-IF-THEN-PER_INSTANCE */ + .......... If-Then constraint + CONSTR-VAR: + PER_INSTANCE: + - | + /* XXX: TODO: CONSTR-VAR-PER_INSTANCE */ + .......... Metric Variable constraint + CONSTR-LOG: + PER_INSTANCE: + - | + /* XXX: TODO: CONSTR-LOG-PER_INSTANCE */ + .......... Logical constraint + VAR: + PER_INSTANCE: + - | + /* XXX: TODO: VAR-PER_INSTANCE */ + .......... Metric Variable \ No newline at end of file diff --git a/nebulous/metric-model/nebulous-metric-model-schema.json b/nebulous/metric-model/nebulous-metric-model-schema.json new file mode 100644 index 0000000..98912ec --- /dev/null +++ b/nebulous/metric-model/nebulous-metric-model-schema.json @@ -0,0 +1,679 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://nebulouscloud.eu/nebulous-metric-model-v1.0.0.schema.json", + "title": "Nebulous Metric Model", + "description": "Nebulous Metric Model is a YAML file defining the monitoring requirements and details of a Nebulous multi-container application. Current version is v.1.0.0, 2023-10", + + "type": "object", + "properties": { + "apiVersion": { + "const": "nebulous/v1" + }, + "kind": { + "const": "MetricModel" + }, + "metadata": { + "type": "object", + "properties": { + "name": { + "description": "The display name of the model", + "type": "string" + } + }, + "additionalProperties": true + }, + "spec": { + "description": "Lists of component and scope with metrics and/or requirements", + "type": "object", + "properties": { + "components": { + "description": "Components list", + "type": "array", + "items": { + "$ref": "#/$defs/component" + } + }, + "scopes": { + "description": "Scopes list", + "type": "array", + "items": { + "$ref": "#/$defs/scope" + } + } + }, + "additionalProperties": false + }, + "functions": { + "description": "Function definitions used in composite metric formulas", + "type": "array", + "items": { + "$ref": "#/$defs/function" + } + } + }, + "required": [ "apiVersion", "kind", "spec" ], + "additionalProperties": true, + + "$defs": { + + "name": { + "id": "#/$defs/name", + "description": "Element name", + "type": "string", + "pattern": "[A-Za-z_][A-Za-z0-9_]*" + }, + + "ref": { + "id": "#/$defs/ref", + "description": "Metric reference", + "type": "string", + "pattern": "^\\s*([A-Za-z_][A-Za-z0-9_\\-]*|\\[[A-Za-z_][A-Za-z0-9_\\-]*\\])(\\s*\\.\\s*([A-Za-z_][A-Za-z0-9_\\-]*|\\[[A-Za-z_][A-Za-z0-9_\\-]*\\]))*\\s*$" + }, + + "grouping": { + "id": "#/$defs/grouping", + "description": "Metrics computation grouping", + "enum": [ + "per_instance", "instance", "PER_INSTANCE", "INSTANCE", + "per_host", "host", "PER_HOST", "HOST", + "per_zone", "zone", "PER_ZONE", "ZONE", + "per_region", "region", "PER_REGION", "REGION", + "per_cloud", "cloud", "PER_CLOUD", "CLOUD", + "global", "GLOBAL" + ] + }, + + "unit": { + "id": "#/$defs/name", + "description": "Units (empty means 'seconds')", + "enum": [ + "event", "events", + "ms", "msec", "milli", "millis", + "s", "sec", "second", "seconds", + "min", "minute", "minutes", + "hr", "hour", "hours", + "d", "day", "days", + "w", "week", "weeks", + "y", "year", "years" + ], + "default": "sec" + }, + + "cep_size": { + "description": "Window size or Schedule", + "type": "object", + "properties": { + "value": { + "description": "Size value (a positive number)", + "type": "number", + "exclusiveMinimum": 0 + }, + "unit": { + "$ref": "#/$defs/unit" + } + }, + "required": [ "value" ], + "additionalProperties": false + }, + + "component": { + "id": "#/$defs/component", + "description": "Component-specific metrics and requirements", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/name" + }, + "requirements": { + "description": "Component requirements list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/requirement" + } + }, + "metrics": { + "description": "Component metrics list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/metric" + } + } + }, + "required": [ "name" ], + "additionalProperties": false + }, + + "scope": { + "id": "#/$defs/scope", + "description": "Scope-specific metrics and requirements", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/name" + }, + "components": { + "description": "Components partitipating in scope ('*' means all components)", + "oneOf": [ + { + "const": "*" + }, + { + "type": "array", + "items": { + "$ref": "#/$defs/name" + } + } + ] + }, + "requirements": { + "description": "Scope requirements list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/requirement" + } + }, + "metrics": { + "description": "Scope metrics list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/metric" + } + } + }, + "required": [ "name" ], + "additionalProperties": false + }, + + "requirement": { + "id": "#/$defs/requirement", + "description": "Requirement (SLO)", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/name" + }, + "type": { + "description": "Requirement type. Currently only SLO's are supported", + "const": "slo" + }, + "constraint": { + "oneOf": [ + { + "description": "SLO constraint in shorthand form. Only metric constraints are allowed in shorthand form. E.g. ", + "type": "string", + "pattern": "^\\s*[A-Za-z_][A-Za-z0-9_]*\\s*[<>=]{1,2}\\s*\\-?\\d+(\\.\\d*)?\\s*$" + }, + { + "description": "SLO metric constraint in detail form", + "type": "object", + "properties": { + "type": { + "description": "Constraint type. Currently only 'metric' constraints are supported", + "const": "metric" + }, + "metric": { + "description": "Name of constraint metric. Must be defined in the metrics list of this component or scope", + "$ref": "#/$defs/name" + }, + "operator": { + "description": "Metric constraint comparison operator", + "enum": [ "=", "<>", "<", "<=", "=<", ">", ">=", "=>" ] + }, + "threshold": { + "description": "Metric constraint threshold (a real number)", + "type": "number" + } + }, + "required": [ "metric", "operator", "threshold" ], + "additionalProperties": false + }, + { + "description": "SLO logical constraint in detail form", + "type": "object", + "properties": { + "type": { + "description": "Constraint type. Currently only 'metric' constraints are supported", + "const": "logical" + }, + "operator": { + "description": "Logical constraint operator", + "enum": [ "and", "or" ] + }, + "constraints": { + "description": "Logical constraint sub-constraints", + "type": "array", + "items": { + "$ref": "#/$defs/name" + } + } + }, + "required": [ "type", "operator", "constraints" ], + "additionalProperties": false + }, + { + "description": "SLO conditional constraint in detail form", + "type": "object", + "properties": { + "type": { + "description": "Constraint type", + "const": "conditional" + }, + "if": { + "description": "Conditional constraint IF clause", + "$ref": "#/$defs/name" + }, + "then": { + "description": "Conditional constraint THEN clause", + "$ref": "#/$defs/name" + }, + "else": { + "description": "Conditional constraint ELSE clause", + "$ref": "#/$defs/name" + } + }, + "required": [ "type", "if", "then" ], + "additionalProperties": false + } + ] + } + }, + "required": [ "name", "constraint" ], + "additionalProperties": false + }, + + "metric": { + "id": "#/$defs/metric", + "description": "Metric related to this component or scope", + "oneOf": [ + { + "$ref": "#/$defs/metric-raw" + }, + { + "$ref": "#/$defs/metric-composite" + }, + { + "$ref": "#/$defs/metric-constant" + }, + { + "$ref": "#/$defs/metric-ref" + } + ] + }, + + "metric-raw": { + "id": "#/$defs/metric-raw", + "description": "Raw metric related to this component or scope", + "type": "object", + "properties": { + "name": { + "description": "Raw metric name", + "$ref": "#/$defs/name" + }, + "type": { + "description": "Raw metric type (always 'raw'. Can be omitted)", + "const": "raw" + }, + "template": { + "description": "Raw metric template (if omitted means any real number)", + "$ref": "#/$defs/template" + }, + "sensor": { + "description": "Raw metric sensor specification", + "$ref": "#/$defs/sensor" + }, + "output": { + "description": "Raw metric output schedule", + "$ref": "#/$defs/output" + }, + "busy-status": { + "description": "is busy-status metric?", + "type": "boolean" + } + }, + "required": [ "name", "sensor" ], + "additionalProperties": false + }, + + "metric-composite": { + "id": "#/$defs/metric-composite", + "description": "Composite related to this component or scope", + "type": "object", + "properties": { + "name": { + "description": "Composite metric name", + "$ref": "#/$defs/name" + }, + "type": { + "description": "Composite metric type (always 'composite'. Can be omitted)", + "const": "composite" + }, + "template": { + "description": "Composite metric template (if omitted means any real number)", + "$ref": "#/$defs/template" + }, + "formula": { + "description": "Composite metric formula. MUST comply with 'mathXParser' syntax", + "type": "string", + "minLength": 1 + }, + "window": { + "description": "Composite metric window specification", + "$ref": "#/$defs/window" + }, + "output": { + "description": "Composite metric output schedule", + "$ref": "#/$defs/output" + }, + "level": { + "description": "Composite metric computation level/grouping", + "$ref": "#/$defs/grouping" + }, + "grouping": { + "description": "Composite metric computation level/grouping", + "$ref": "#/$defs/grouping" + }, + "busy-status": { + "description": "is busy-status metric?", + "type": "boolean" + } + }, + "required": [ "name", "formula" ], + "additionalProperties": false + }, + + "metric-constant": { + "id": "#/$defs/metric-constant", + "description": "Constant related to this component or scope", + "type": "object", + "properties": { + "name": { + "description": "Constant name", + "$ref": "#/$defs/name" + }, + "type": { + "description": "Constant type (always 'constant'. CANNOT BE OMITTED)", + "const": "constant" + }, + "template": { + "description": "Constant metric template (if omitted means any real number)", + "$ref": "#/$defs/template" + }, + "initial": { + "description": "Constant's initial value. NOTE: If omitted errors may occur at runtime until a value is provided", + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "required": [ "name", "type" ], + "additionalProperties": false + }, + + "metric-ref": { + "id": "#/$defs/metric-ref", + "description": "Reference to another metric in this or another component or scope", + "type": "object", + "properties": { + "name": { + "description": "Metric name", + "$ref": "#/$defs/name" + }, + "ref": { + "description": "Reference to another metric. Form: '.', COMPONET_NAME/SCOPE_NAME can be omitted if referenced metric is in the same component or scope", + "$ref": "#/$defs/ref" + } + }, + "required": [ "name", "ref" ], + "additionalProperties": false + }, + + "template": { + "id": "#/$defs/template", + "description": "Metric template for metrics and constants. If omitted, the metric or constant value range is assumed to be any real number", + "type": "object", + "properties": { + "id": { + "description": "Template Id. Reserved for future use.", + "type": "string" + }, + "type": { + "description": "Metric template value type", + "enum": [ "int", "integer", "double", "float", "real" ] + }, + "range": { + "description": "Metric template value range. Range bounds must be of the type specified in 'type' property", + "type": "array", + "prefixItems": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "minItems": 2, + "maxItems": 2 + }, + "unit": { + "description": "Template unit (can be omitted)", + "type": "string" + } + }, + "required": [ "type" ], + "additionalProperties": false + }, + + "sensor": { + "id": "#/$defs/sensor", + "description": "Sensor specification for a raw metric", + "oneOf": [ + { + "description": "Sensor specification in shorthand form. Only 'netdata' sensors allowed. Form: 'netdata ', e.g. 'netdata netdata__system__cpu__user'", + "type": "string", + "pattern": "^\\s*netdata\\s*[A-Za-z0-9_]+\\s*$" + }, + { + "description": "Sensor specification in detail form", + "type": "object", + "properties": { + "type": { + "description": "Sensor type. If omitted 'netdata' sensor is assumed", + "type": "string", + "minLength": 1 + }, + "affinity": { + "description": "Netdata sensors only. The EMS_NETDATA_TOPIC. E.g. ''netdata__system__cpu__user'", + "type": "string", + "minLength": 1 + }, + "config": { + "description": "Sensor specific configuration. Typically needed for custom sensors", + "type": "object" + }, + "install": { + "description": "Sensor installation scripts. NOTE: Reserved for future use", + "type": "object" + } + }, + "required": [ "type" ], + "additionalProperties": false + } + ] + }, + + "window": { + "id": "#/$defs/window", + "description": "Composite metric window. Windows are memory buffers retaining incoming events until a time or size condition is met.", + "oneOf": [ + { + "description": "Window specification in shorthand form. Form: , e.g. 'sliding 5 minutes'", + "type": "string", + "pattern": "^\\s*(sliding|batch)\\s+\\d+(\\.\\d*)?\\s*[AZ=a-z]+\\s*$" + }, + { + "description": "Window specification in detail form", + "type": "object", + "properties": { + "type": { + "description": "Window type: sliding or batch", + "enum": [ "batch", "sliding" ] + }, + "size": { + "description": "Window size", + "oneOf": [ + { + "description": "Window size in shorthand form. Form: , e.g. '30 seconds'", + "type": "string", + "pattern": "^\\s*\\d+(\\.\\d*)?\\s*[A-Za-z]*\\s*$" + }, + { + "description": "Window size in detail form", + "$ref": "#/$defs/cep_size" + } + ] + }, + "processing": { + "description": "Window processings list", + "type": "array", + "items": { + "$ref": "#/$defs/processing" + } + } + }, + "required": [ "type", "size" ], + "additionalProperties": false + } + ] + }, + + "processing": { + "id": "#/$defs/processing", + "description": "Window processing (i.e. group and sort, or rank)", + "properties": { + "type": { + "description": "Window processing type (group, sort, rank)", + "enum": [ "group", "sort", "rank" ] + }, + "function": { + "description": "Window processing EPL function", + "type": "string", + "minLength": 1 + }, + "criteria": { + "description": "Window processing criteria list. At least one must be provided", + "type": "array", + "items": { + "$ref": "#/$defs/criteria", + "minItems": 1 + }, + "uniqueItems": true + } + }, + "required": [ "type", "criteria" ], + "additionalProperties": false + }, + + "criteria": { + "id": "#/$defs/criteria", + "description": "Window processing criterion (for grouping, or sorting)", + "oneOf": [ + { + "$ref": "#/$defs/grouping" + }, + { + "enum": [ "timestamp", "TIMESTAMP" ] + }, + { + "type": "object", + "properties": { + "type": { + "enum": [ "custom", "CUSTOM" ] + }, + "custom": { + "type": "string", + "minLength": 1 + } + }, + "required": [ "custom" ], + "additionalProperties": false + } + ] + }, + + "output": { + "id": "#/$defs/output", + "description": "Output schedule for metrics. Controls how often the metric values are published to EMS (meanwhile they are cached in memory)", + "oneOf": [ + { + "description": "Output specification in shorthand form. Form: , e.g. 'all 30 seconds'", + "type": "string", + "pattern": "^\\s*((all|first|last|snapshot)\\s)?\\s*\\d+(\\.\\d*)?\\s*[A-Za-z]*\\s*$" + }, + { + "description": "Output specification in detail form", + "type": "object", + "properties": { + "type": { + "description": "Output type. Controls which (cached) metric values will be published to EMS (all, first, last, snapshot)", + "enum": [ "all", "first", "last", "snapshot" ], + "default": "all" + }, + "schedule": { + "description": "Output schedule", + "oneOf": [ + { + "description": "Output schedule in shorthand form. Form: , e.g. '30 seconds'", + "type": "string", + "pattern": "^\\s*\\d+(\\.\\d*)?\\s*[A-Za-z]*\\s*$" + }, + { + "description": "Output schedule in detail form", + "$ref": "#/$defs/cep_size" + } + ] + } + }, + "required": [ "schedule" ], + "additionalProperties": false + } + ] + }, + + "function": { + "id": "#/$defs/function", + "description": "Function definition. Functions can be used in composite metric formulas.", + "type": "object", + "properties": { + "name": { + "description": "Function name. MUST BE UNIQUE. It can be used in composite metric formulas.", + "$ref": "#/$defs/name" + }, + "expression": { + "description": "Function expression. MUST comply with 'mathXParser' syntax", + "type": "string", + "minLength": 1 + }, + "arguments": { + "description": "Function arguments. They MUST match to those used in 'expression' both in number and names.", + "type": "array", + "items": { + "description": "Function argument. MUST be used in the corresponing function expression.", + "$ref": "#/$defs/name" + } + } + }, + "required": [ "name", "expression", "arguments" ], + "additionalProperties": false + } + + } +} diff --git a/nebulous/metric-model/nebulous-metric-model-v1.0.0-schema.json b/nebulous/metric-model/nebulous-metric-model-v1.0.0-schema.json new file mode 100644 index 0000000..98912ec --- /dev/null +++ b/nebulous/metric-model/nebulous-metric-model-v1.0.0-schema.json @@ -0,0 +1,679 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://nebulouscloud.eu/nebulous-metric-model-v1.0.0.schema.json", + "title": "Nebulous Metric Model", + "description": "Nebulous Metric Model is a YAML file defining the monitoring requirements and details of a Nebulous multi-container application. Current version is v.1.0.0, 2023-10", + + "type": "object", + "properties": { + "apiVersion": { + "const": "nebulous/v1" + }, + "kind": { + "const": "MetricModel" + }, + "metadata": { + "type": "object", + "properties": { + "name": { + "description": "The display name of the model", + "type": "string" + } + }, + "additionalProperties": true + }, + "spec": { + "description": "Lists of component and scope with metrics and/or requirements", + "type": "object", + "properties": { + "components": { + "description": "Components list", + "type": "array", + "items": { + "$ref": "#/$defs/component" + } + }, + "scopes": { + "description": "Scopes list", + "type": "array", + "items": { + "$ref": "#/$defs/scope" + } + } + }, + "additionalProperties": false + }, + "functions": { + "description": "Function definitions used in composite metric formulas", + "type": "array", + "items": { + "$ref": "#/$defs/function" + } + } + }, + "required": [ "apiVersion", "kind", "spec" ], + "additionalProperties": true, + + "$defs": { + + "name": { + "id": "#/$defs/name", + "description": "Element name", + "type": "string", + "pattern": "[A-Za-z_][A-Za-z0-9_]*" + }, + + "ref": { + "id": "#/$defs/ref", + "description": "Metric reference", + "type": "string", + "pattern": "^\\s*([A-Za-z_][A-Za-z0-9_\\-]*|\\[[A-Za-z_][A-Za-z0-9_\\-]*\\])(\\s*\\.\\s*([A-Za-z_][A-Za-z0-9_\\-]*|\\[[A-Za-z_][A-Za-z0-9_\\-]*\\]))*\\s*$" + }, + + "grouping": { + "id": "#/$defs/grouping", + "description": "Metrics computation grouping", + "enum": [ + "per_instance", "instance", "PER_INSTANCE", "INSTANCE", + "per_host", "host", "PER_HOST", "HOST", + "per_zone", "zone", "PER_ZONE", "ZONE", + "per_region", "region", "PER_REGION", "REGION", + "per_cloud", "cloud", "PER_CLOUD", "CLOUD", + "global", "GLOBAL" + ] + }, + + "unit": { + "id": "#/$defs/name", + "description": "Units (empty means 'seconds')", + "enum": [ + "event", "events", + "ms", "msec", "milli", "millis", + "s", "sec", "second", "seconds", + "min", "minute", "minutes", + "hr", "hour", "hours", + "d", "day", "days", + "w", "week", "weeks", + "y", "year", "years" + ], + "default": "sec" + }, + + "cep_size": { + "description": "Window size or Schedule", + "type": "object", + "properties": { + "value": { + "description": "Size value (a positive number)", + "type": "number", + "exclusiveMinimum": 0 + }, + "unit": { + "$ref": "#/$defs/unit" + } + }, + "required": [ "value" ], + "additionalProperties": false + }, + + "component": { + "id": "#/$defs/component", + "description": "Component-specific metrics and requirements", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/name" + }, + "requirements": { + "description": "Component requirements list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/requirement" + } + }, + "metrics": { + "description": "Component metrics list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/metric" + } + } + }, + "required": [ "name" ], + "additionalProperties": false + }, + + "scope": { + "id": "#/$defs/scope", + "description": "Scope-specific metrics and requirements", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/name" + }, + "components": { + "description": "Components partitipating in scope ('*' means all components)", + "oneOf": [ + { + "const": "*" + }, + { + "type": "array", + "items": { + "$ref": "#/$defs/name" + } + } + ] + }, + "requirements": { + "description": "Scope requirements list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/requirement" + } + }, + "metrics": { + "description": "Scope metrics list", + "type": "array", + "items": { + "type": "object", + "$ref": "#/$defs/metric" + } + } + }, + "required": [ "name" ], + "additionalProperties": false + }, + + "requirement": { + "id": "#/$defs/requirement", + "description": "Requirement (SLO)", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/name" + }, + "type": { + "description": "Requirement type. Currently only SLO's are supported", + "const": "slo" + }, + "constraint": { + "oneOf": [ + { + "description": "SLO constraint in shorthand form. Only metric constraints are allowed in shorthand form. E.g. ", + "type": "string", + "pattern": "^\\s*[A-Za-z_][A-Za-z0-9_]*\\s*[<>=]{1,2}\\s*\\-?\\d+(\\.\\d*)?\\s*$" + }, + { + "description": "SLO metric constraint in detail form", + "type": "object", + "properties": { + "type": { + "description": "Constraint type. Currently only 'metric' constraints are supported", + "const": "metric" + }, + "metric": { + "description": "Name of constraint metric. Must be defined in the metrics list of this component or scope", + "$ref": "#/$defs/name" + }, + "operator": { + "description": "Metric constraint comparison operator", + "enum": [ "=", "<>", "<", "<=", "=<", ">", ">=", "=>" ] + }, + "threshold": { + "description": "Metric constraint threshold (a real number)", + "type": "number" + } + }, + "required": [ "metric", "operator", "threshold" ], + "additionalProperties": false + }, + { + "description": "SLO logical constraint in detail form", + "type": "object", + "properties": { + "type": { + "description": "Constraint type. Currently only 'metric' constraints are supported", + "const": "logical" + }, + "operator": { + "description": "Logical constraint operator", + "enum": [ "and", "or" ] + }, + "constraints": { + "description": "Logical constraint sub-constraints", + "type": "array", + "items": { + "$ref": "#/$defs/name" + } + } + }, + "required": [ "type", "operator", "constraints" ], + "additionalProperties": false + }, + { + "description": "SLO conditional constraint in detail form", + "type": "object", + "properties": { + "type": { + "description": "Constraint type", + "const": "conditional" + }, + "if": { + "description": "Conditional constraint IF clause", + "$ref": "#/$defs/name" + }, + "then": { + "description": "Conditional constraint THEN clause", + "$ref": "#/$defs/name" + }, + "else": { + "description": "Conditional constraint ELSE clause", + "$ref": "#/$defs/name" + } + }, + "required": [ "type", "if", "then" ], + "additionalProperties": false + } + ] + } + }, + "required": [ "name", "constraint" ], + "additionalProperties": false + }, + + "metric": { + "id": "#/$defs/metric", + "description": "Metric related to this component or scope", + "oneOf": [ + { + "$ref": "#/$defs/metric-raw" + }, + { + "$ref": "#/$defs/metric-composite" + }, + { + "$ref": "#/$defs/metric-constant" + }, + { + "$ref": "#/$defs/metric-ref" + } + ] + }, + + "metric-raw": { + "id": "#/$defs/metric-raw", + "description": "Raw metric related to this component or scope", + "type": "object", + "properties": { + "name": { + "description": "Raw metric name", + "$ref": "#/$defs/name" + }, + "type": { + "description": "Raw metric type (always 'raw'. Can be omitted)", + "const": "raw" + }, + "template": { + "description": "Raw metric template (if omitted means any real number)", + "$ref": "#/$defs/template" + }, + "sensor": { + "description": "Raw metric sensor specification", + "$ref": "#/$defs/sensor" + }, + "output": { + "description": "Raw metric output schedule", + "$ref": "#/$defs/output" + }, + "busy-status": { + "description": "is busy-status metric?", + "type": "boolean" + } + }, + "required": [ "name", "sensor" ], + "additionalProperties": false + }, + + "metric-composite": { + "id": "#/$defs/metric-composite", + "description": "Composite related to this component or scope", + "type": "object", + "properties": { + "name": { + "description": "Composite metric name", + "$ref": "#/$defs/name" + }, + "type": { + "description": "Composite metric type (always 'composite'. Can be omitted)", + "const": "composite" + }, + "template": { + "description": "Composite metric template (if omitted means any real number)", + "$ref": "#/$defs/template" + }, + "formula": { + "description": "Composite metric formula. MUST comply with 'mathXParser' syntax", + "type": "string", + "minLength": 1 + }, + "window": { + "description": "Composite metric window specification", + "$ref": "#/$defs/window" + }, + "output": { + "description": "Composite metric output schedule", + "$ref": "#/$defs/output" + }, + "level": { + "description": "Composite metric computation level/grouping", + "$ref": "#/$defs/grouping" + }, + "grouping": { + "description": "Composite metric computation level/grouping", + "$ref": "#/$defs/grouping" + }, + "busy-status": { + "description": "is busy-status metric?", + "type": "boolean" + } + }, + "required": [ "name", "formula" ], + "additionalProperties": false + }, + + "metric-constant": { + "id": "#/$defs/metric-constant", + "description": "Constant related to this component or scope", + "type": "object", + "properties": { + "name": { + "description": "Constant name", + "$ref": "#/$defs/name" + }, + "type": { + "description": "Constant type (always 'constant'. CANNOT BE OMITTED)", + "const": "constant" + }, + "template": { + "description": "Constant metric template (if omitted means any real number)", + "$ref": "#/$defs/template" + }, + "initial": { + "description": "Constant's initial value. NOTE: If omitted errors may occur at runtime until a value is provided", + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "required": [ "name", "type" ], + "additionalProperties": false + }, + + "metric-ref": { + "id": "#/$defs/metric-ref", + "description": "Reference to another metric in this or another component or scope", + "type": "object", + "properties": { + "name": { + "description": "Metric name", + "$ref": "#/$defs/name" + }, + "ref": { + "description": "Reference to another metric. Form: '.', COMPONET_NAME/SCOPE_NAME can be omitted if referenced metric is in the same component or scope", + "$ref": "#/$defs/ref" + } + }, + "required": [ "name", "ref" ], + "additionalProperties": false + }, + + "template": { + "id": "#/$defs/template", + "description": "Metric template for metrics and constants. If omitted, the metric or constant value range is assumed to be any real number", + "type": "object", + "properties": { + "id": { + "description": "Template Id. Reserved for future use.", + "type": "string" + }, + "type": { + "description": "Metric template value type", + "enum": [ "int", "integer", "double", "float", "real" ] + }, + "range": { + "description": "Metric template value range. Range bounds must be of the type specified in 'type' property", + "type": "array", + "prefixItems": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "minItems": 2, + "maxItems": 2 + }, + "unit": { + "description": "Template unit (can be omitted)", + "type": "string" + } + }, + "required": [ "type" ], + "additionalProperties": false + }, + + "sensor": { + "id": "#/$defs/sensor", + "description": "Sensor specification for a raw metric", + "oneOf": [ + { + "description": "Sensor specification in shorthand form. Only 'netdata' sensors allowed. Form: 'netdata ', e.g. 'netdata netdata__system__cpu__user'", + "type": "string", + "pattern": "^\\s*netdata\\s*[A-Za-z0-9_]+\\s*$" + }, + { + "description": "Sensor specification in detail form", + "type": "object", + "properties": { + "type": { + "description": "Sensor type. If omitted 'netdata' sensor is assumed", + "type": "string", + "minLength": 1 + }, + "affinity": { + "description": "Netdata sensors only. The EMS_NETDATA_TOPIC. E.g. ''netdata__system__cpu__user'", + "type": "string", + "minLength": 1 + }, + "config": { + "description": "Sensor specific configuration. Typically needed for custom sensors", + "type": "object" + }, + "install": { + "description": "Sensor installation scripts. NOTE: Reserved for future use", + "type": "object" + } + }, + "required": [ "type" ], + "additionalProperties": false + } + ] + }, + + "window": { + "id": "#/$defs/window", + "description": "Composite metric window. Windows are memory buffers retaining incoming events until a time or size condition is met.", + "oneOf": [ + { + "description": "Window specification in shorthand form. Form: , e.g. 'sliding 5 minutes'", + "type": "string", + "pattern": "^\\s*(sliding|batch)\\s+\\d+(\\.\\d*)?\\s*[AZ=a-z]+\\s*$" + }, + { + "description": "Window specification in detail form", + "type": "object", + "properties": { + "type": { + "description": "Window type: sliding or batch", + "enum": [ "batch", "sliding" ] + }, + "size": { + "description": "Window size", + "oneOf": [ + { + "description": "Window size in shorthand form. Form: , e.g. '30 seconds'", + "type": "string", + "pattern": "^\\s*\\d+(\\.\\d*)?\\s*[A-Za-z]*\\s*$" + }, + { + "description": "Window size in detail form", + "$ref": "#/$defs/cep_size" + } + ] + }, + "processing": { + "description": "Window processings list", + "type": "array", + "items": { + "$ref": "#/$defs/processing" + } + } + }, + "required": [ "type", "size" ], + "additionalProperties": false + } + ] + }, + + "processing": { + "id": "#/$defs/processing", + "description": "Window processing (i.e. group and sort, or rank)", + "properties": { + "type": { + "description": "Window processing type (group, sort, rank)", + "enum": [ "group", "sort", "rank" ] + }, + "function": { + "description": "Window processing EPL function", + "type": "string", + "minLength": 1 + }, + "criteria": { + "description": "Window processing criteria list. At least one must be provided", + "type": "array", + "items": { + "$ref": "#/$defs/criteria", + "minItems": 1 + }, + "uniqueItems": true + } + }, + "required": [ "type", "criteria" ], + "additionalProperties": false + }, + + "criteria": { + "id": "#/$defs/criteria", + "description": "Window processing criterion (for grouping, or sorting)", + "oneOf": [ + { + "$ref": "#/$defs/grouping" + }, + { + "enum": [ "timestamp", "TIMESTAMP" ] + }, + { + "type": "object", + "properties": { + "type": { + "enum": [ "custom", "CUSTOM" ] + }, + "custom": { + "type": "string", + "minLength": 1 + } + }, + "required": [ "custom" ], + "additionalProperties": false + } + ] + }, + + "output": { + "id": "#/$defs/output", + "description": "Output schedule for metrics. Controls how often the metric values are published to EMS (meanwhile they are cached in memory)", + "oneOf": [ + { + "description": "Output specification in shorthand form. Form: , e.g. 'all 30 seconds'", + "type": "string", + "pattern": "^\\s*((all|first|last|snapshot)\\s)?\\s*\\d+(\\.\\d*)?\\s*[A-Za-z]*\\s*$" + }, + { + "description": "Output specification in detail form", + "type": "object", + "properties": { + "type": { + "description": "Output type. Controls which (cached) metric values will be published to EMS (all, first, last, snapshot)", + "enum": [ "all", "first", "last", "snapshot" ], + "default": "all" + }, + "schedule": { + "description": "Output schedule", + "oneOf": [ + { + "description": "Output schedule in shorthand form. Form: , e.g. '30 seconds'", + "type": "string", + "pattern": "^\\s*\\d+(\\.\\d*)?\\s*[A-Za-z]*\\s*$" + }, + { + "description": "Output schedule in detail form", + "$ref": "#/$defs/cep_size" + } + ] + } + }, + "required": [ "schedule" ], + "additionalProperties": false + } + ] + }, + + "function": { + "id": "#/$defs/function", + "description": "Function definition. Functions can be used in composite metric formulas.", + "type": "object", + "properties": { + "name": { + "description": "Function name. MUST BE UNIQUE. It can be used in composite metric formulas.", + "$ref": "#/$defs/name" + }, + "expression": { + "description": "Function expression. MUST comply with 'mathXParser' syntax", + "type": "string", + "minLength": 1 + }, + "arguments": { + "description": "Function arguments. They MUST match to those used in 'expression' both in number and names.", + "type": "array", + "items": { + "description": "Function argument. MUST be used in the corresponing function expression.", + "$ref": "#/$defs/name" + } + } + }, + "required": [ "name", "expression", "arguments" ], + "additionalProperties": false + } + + } +} diff --git a/nebulous/pom.xml b/nebulous/pom.xml new file mode 100644 index 0000000..9512f9d --- /dev/null +++ b/nebulous/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + Event Management System for Nebulous + gr.iccs.imu.ems + ems-nebublous + 7.8.9 + pom + + + ems-core + ems-nebulous + + + \ No newline at end of file diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index b688b5b..e54763f 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -8,15 +8,15 @@ - nebulous-monitoring-container-images description: Build the container images. files: &image_files - - ^java-spring-boot-demo/ + - ^nebulous/ vars: &image_vars promote_container_image_job: nebulous-monitoring-upload-container-images container_images: - - context: java-spring-boot-demo + - context: nebulous registry: quay.io - repository: quay.io/nebulous/monitoring-java-spring-boot-demo + repository: quay.io/nebulous/monitoring namespace: nebulous - repo_shortname: monitoring-java-spring-boot-demo + repo_shortname: monitoring repo_description: "" - job: @@ -44,7 +44,7 @@ description: Run Hadolint on Dockerfile(s). vars: dockerfiles: - - java-spring-boot-demo/Dockerfile + - nebulous/Dockerfile - job: name: nebulous-monitoring-helm-lint