diff --git a/adaptation/src/main/java/org/iobserve/adaptation/stages/ComposedActionComputation.java b/adaptation/src/main/java/org/iobserve/adaptation/stages/ComposedActionComputation.java new file mode 100644 index 00000000..4762252e --- /dev/null +++ b/adaptation/src/main/java/org/iobserve/adaptation/stages/ComposedActionComputation.java @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.adaptation.stages; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import teetime.stage.basic.AbstractTransformation; + +import org.iobserve.adaptation.data.AdaptationData; +import org.iobserve.adaptation.data.graph.HostComponentAllocationGraph; +import org.iobserve.planning.systemadaptation.SystemAdaptation; +import org.iobserve.planning.systemadaptation.SystemadaptationFactory; +import org.kie.api.KieServices; +import org.kie.api.command.Command; +import org.kie.api.command.KieCommands; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.StatelessKieSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Receives an AdaptationData record containing the runtime model graph as well as the redeployment + * model graph. Inserts both graphs into the drools rule engine and receives a + * {@link SystemAdaptation} model containing a list of composed (high-level) adaptation actions + * which is passed to the output port. + * + * @author Lars Bluemke + * + */ +public class ComposedActionComputation extends AbstractTransformation { + // Logger is invoked from drools rule file + public static final Logger LOGGER = LoggerFactory.getLogger(ComposedActionComputation.class); + + private final KieServices kieServices = KieServices.Factory.get(); + private final KieContainer kContainer = this.kieServices.getKieClasspathContainer(); + private final StatelessKieSession kSession = this.kContainer.newStatelessKieSession(); + private final KieCommands kieCommands = this.kieServices.getCommands(); + + @Override + protected void execute(final AdaptationData adaptationData) throws Exception { + final HostComponentAllocationGraph runtimeGraph = adaptationData.getRuntimeGraph(); + final HostComponentAllocationGraph redeploymentGraph = adaptationData.getReDeploymentGraph(); + final List> workingMemoryInserts = new ArrayList<>(); + final SystemAdaptation systemAdaptationModel = SystemadaptationFactory.eINSTANCE.createSystemAdaptation(); + + // Add system adaptation model (its list of actions will be filled with by the rule engine) + workingMemoryInserts.add(this.kieCommands.newInsert(systemAdaptationModel)); + + // Add component nodes and deployment nodes of runtime and redeployment model graph + this.addToWorkingMemoryInserts(workingMemoryInserts, runtimeGraph.getComponents()); + this.addToWorkingMemoryInserts(workingMemoryInserts, runtimeGraph.getServers()); + this.addToWorkingMemoryInserts(workingMemoryInserts, redeploymentGraph.getComponents()); + this.addToWorkingMemoryInserts(workingMemoryInserts, redeploymentGraph.getServers()); + + // Execute rule engine which will add actions to composedAdaptationActions + this.kSession.execute(this.kieCommands.newBatchExecution(workingMemoryInserts)); + + this.outputPort.send(systemAdaptationModel); + } + + private void addToWorkingMemoryInserts(final List> inserts, final Set graphComponents) { + for (final Object component : graphComponents) { + inserts.add(this.kieCommands.newInsert(component)); + } + } + +} diff --git a/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/AllocateAction2AtomicActions.java b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/AllocateAction2AtomicActions.java new file mode 100644 index 00000000..7c710972 --- /dev/null +++ b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/AllocateAction2AtomicActions.java @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.adaptation.stages.transformations; + +import java.util.ArrayList; +import java.util.List; + +import org.iobserve.adaptation.executionplan.AtomicAction; +import org.iobserve.adaptation.executionplan.AtomicActionFactory; +import org.iobserve.planning.systemadaptation.AllocateAction; + +/** + * Creates the necessary atomic actions to execute an allocation. + * + * @author Lars Bluemke + * + */ +public class AllocateAction2AtomicActions implements IComposed2AtomicAction { + + @Override + public List transform(final AllocateAction allocateAction) { + final List atomicActions = new ArrayList<>(); + + // Allocate Node + atomicActions.add(AtomicActionFactory.generateAllocateNodeAction(allocateAction.getTargetResourceContainer())); + + // Connect Node + atomicActions.add(AtomicActionFactory.generateConnectNodeAction(allocateAction.getTargetResourceContainer(), + allocateAction.getTargetLinkingResources())); + + return atomicActions; + } + +} diff --git a/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/ChangeComponentAction2AtomicActions.java b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/ChangeComponentAction2AtomicActions.java new file mode 100644 index 00000000..8399b76a --- /dev/null +++ b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/ChangeComponentAction2AtomicActions.java @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.adaptation.stages.transformations; + +import java.util.ArrayList; +import java.util.List; + +import org.iobserve.adaptation.executionplan.AtomicAction; +import org.iobserve.adaptation.executionplan.AtomicActionFactory; +import org.iobserve.planning.systemadaptation.ChangeRepositoryComponentAction; + +/** + * Creates the necessary atomic actions to execute a change repository component action. + * + * @author Lars Bluemke + * + */ +public class ChangeComponentAction2AtomicActions implements IComposed2AtomicAction { + + @Override + public List transform(final ChangeRepositoryComponentAction changeComponentAction) { + final List atomicActions = new ArrayList<>(); + + // Deploy new component instance + atomicActions.add( + AtomicActionFactory.generateDeployComponentAction(changeComponentAction.getTargetAllocationContext())); + + // Migrate state + atomicActions.add(AtomicActionFactory.generateMigrateComponentStateAction( + changeComponentAction.getSourceAllocationContext(), + changeComponentAction.getTargetAllocationContext())); + + // Connect replication + atomicActions.add( + AtomicActionFactory.generateConnectComponentAction(changeComponentAction.getTargetAllocationContext(), + changeComponentAction.getTargetProvidingAllocationContexts(), + changeComponentAction.getTargetRequiringAllocationContexts())); + + // Block incoming requests + atomicActions.add(AtomicActionFactory.generateBlockRequestsToComponentAction( + changeComponentAction.getSourceAllocationContext(), + changeComponentAction.getTargetRequiringAllocationContexts())); + + // Finish running transactions + atomicActions.add( + AtomicActionFactory.generateFinishComponentAction(changeComponentAction.getSourceAllocationContext())); + + // Disconnect component instance + atomicActions.add(AtomicActionFactory.generateDisconnectComponentAction( + changeComponentAction.getSourceAllocationContext(), + changeComponentAction.getTargetProvidingAllocationContexts(), + changeComponentAction.getTargetRequiringAllocationContexts())); + + // Undeploy component instance + atomicActions.add(AtomicActionFactory + .generateUndeployComponentAction(changeComponentAction.getSourceAllocationContext())); + + return atomicActions; + } + +} diff --git a/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/DeallocateAction2AtomicActions.java b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/DeallocateAction2AtomicActions.java new file mode 100644 index 00000000..5b9992a0 --- /dev/null +++ b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/DeallocateAction2AtomicActions.java @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.adaptation.stages.transformations; + +import java.util.ArrayList; +import java.util.List; + +import org.iobserve.adaptation.executionplan.AtomicAction; +import org.iobserve.adaptation.executionplan.AtomicActionFactory; +import org.iobserve.planning.systemadaptation.DeallocateAction; + +/** + * Creates the necessary atomic actions to execute a deallocation. + * + * @author Lars Bluemke + * + */ +public class DeallocateAction2AtomicActions implements IComposed2AtomicAction { + + @Override + public List transform(final DeallocateAction deallocateAction) { + final List atomicActions = new ArrayList<>(); + + // Disconnect Node + atomicActions.add(AtomicActionFactory.generateDisonnectNodeAction(deallocateAction.getTargetResourceContainer(), + deallocateAction.getTargetLinkingResources())); + + // Deallocate Node + atomicActions + .add(AtomicActionFactory.generateDeallocateNodeAction(deallocateAction.getTargetResourceContainer())); + + return atomicActions; + } + +} diff --git a/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/DereplicateAction2AtomicActions.java b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/DereplicateAction2AtomicActions.java new file mode 100644 index 00000000..8574de61 --- /dev/null +++ b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/DereplicateAction2AtomicActions.java @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.adaptation.stages.transformations; + +import java.util.ArrayList; +import java.util.List; + +import org.iobserve.adaptation.executionplan.AtomicAction; +import org.iobserve.adaptation.executionplan.AtomicActionFactory; +import org.iobserve.planning.systemadaptation.DereplicateAction; + +/** + * Creates the necessary atomic actions to execute a dereplication. + * + * @author Lars Bluemke + * + */ +public class DereplicateAction2AtomicActions implements IComposed2AtomicAction { + + @Override + public List transform(final DereplicateAction dereplicateAction) { + final List atomicActions = new ArrayList<>(); + + // Block incoming requests + atomicActions.add(AtomicActionFactory.generateBlockRequestsToComponentAction( + dereplicateAction.getTargetAllocationContext(), + dereplicateAction.getTargetRequiringAllocationContexts())); + + // Finish running transactions + atomicActions + .add(AtomicActionFactory.generateFinishComponentAction(dereplicateAction.getTargetAllocationContext())); + + // Disconnect component instance + atomicActions.add( + AtomicActionFactory.generateDisconnectComponentAction(dereplicateAction.getTargetAllocationContext(), + dereplicateAction.getTargetProvidingAllocationContexts(), + dereplicateAction.getTargetRequiringAllocationContexts())); + + // Undeploy component instance + atomicActions.add( + AtomicActionFactory.generateUndeployComponentAction(dereplicateAction.getTargetAllocationContext())); + + return atomicActions; + } + +} diff --git a/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/MigrateAction2AtomicActions.java b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/MigrateAction2AtomicActions.java new file mode 100644 index 00000000..f47dc1c3 --- /dev/null +++ b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/MigrateAction2AtomicActions.java @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.adaptation.stages.transformations; + +import java.util.ArrayList; +import java.util.List; + +import org.iobserve.adaptation.executionplan.AtomicAction; +import org.iobserve.adaptation.executionplan.AtomicActionFactory; +import org.iobserve.planning.systemadaptation.MigrateAction; + +/** + * Creates the necessary atomic actions to execute a migration. + * + * @author Lars Bluemke + * + */ +public class MigrateAction2AtomicActions implements IComposed2AtomicAction { + + @Override + public List transform(final MigrateAction migrateAction) { + final List atomicActions = new ArrayList<>(); + + // Deploy new component instance + atomicActions + .add(AtomicActionFactory.generateDeployComponentAction(migrateAction.getTargetAllocationContext())); + + // Migrate state + atomicActions.add(AtomicActionFactory.generateMigrateComponentStateAction( + migrateAction.getSourceAllocationContext(), migrateAction.getTargetAllocationContext())); + + // Connect replication + atomicActions.add(AtomicActionFactory.generateConnectComponentAction(migrateAction.getTargetAllocationContext(), + migrateAction.getTargetProvidingAllocationContexts(), + migrateAction.getTargetRequiringAllocationContexts())); + + // Block incoming requests + atomicActions.add(AtomicActionFactory.generateBlockRequestsToComponentAction( + migrateAction.getSourceAllocationContext(), migrateAction.getSourceRequiringAllocationContexts())); + + // Finish running transactions + atomicActions + .add(AtomicActionFactory.generateFinishComponentAction(migrateAction.getSourceAllocationContext())); + + // Disconnect component instance + atomicActions.add(AtomicActionFactory.generateDisconnectComponentAction( + migrateAction.getSourceAllocationContext(), migrateAction.getSourceProvidingAllocationContexts(), + migrateAction.getSourceRequiringAllocationContexts())); + + // Undeploy component instance + atomicActions + .add(AtomicActionFactory.generateUndeployComponentAction(migrateAction.getSourceAllocationContext())); + + return atomicActions; + } + +} diff --git a/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/ReplicateAction2AtomicActions.java b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/ReplicateAction2AtomicActions.java new file mode 100644 index 00000000..23a0d0ef --- /dev/null +++ b/adaptation/src/main/java/org/iobserve/adaptation/stages/transformations/ReplicateAction2AtomicActions.java @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.adaptation.stages.transformations; + +import java.util.ArrayList; +import java.util.List; + +import org.iobserve.adaptation.executionplan.AtomicAction; +import org.iobserve.adaptation.executionplan.AtomicActionFactory; +import org.iobserve.planning.systemadaptation.ReplicateAction; + +/** + * Creates the necessary atomic actions to execute a replication. + * + * @author Lars Bluemke + * + */ +public class ReplicateAction2AtomicActions implements IComposed2AtomicAction { + + @Override + public List transform(final ReplicateAction replicateAction) { + final List atomicActions = new ArrayList<>(); + + // Deploy new component instance + atomicActions + .add(AtomicActionFactory.generateDeployComponentAction(replicateAction.getTargetAllocationContext())); + + // Migrate state + atomicActions.add(AtomicActionFactory.generateMigrateComponentStateAction( + replicateAction.getSourceAllocationContext(), replicateAction.getTargetAllocationContext())); + + // Connect replication + atomicActions.add(AtomicActionFactory.generateConnectComponentAction( + replicateAction.getTargetAllocationContext(), replicateAction.getTargetProvidingAllocationContexts(), + replicateAction.getTargetRequiringAllocationContexts())); + + return atomicActions; + } + +} diff --git a/execution/src/main/java/org/iobserve/execution/configurations/KubernetesExecutionConfiguration.java b/execution/src/main/java/org/iobserve/execution/configurations/KubernetesExecutionConfiguration.java new file mode 100644 index 00000000..2c523700 --- /dev/null +++ b/execution/src/main/java/org/iobserve/execution/configurations/KubernetesExecutionConfiguration.java @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.execution.configurations; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import teetime.framework.Configuration; + +import org.iobserve.execution.stages.AtomicActionExecution; +import org.iobserve.execution.stages.ExecutionPlan2AtomicActions; +import org.iobserve.execution.stages.ExecutionPlanDeserialization; +import org.iobserve.execution.stages.ModelCollector; +import org.iobserve.execution.stages.kubernetes.AllocationExecutor; +import org.iobserve.execution.stages.kubernetes.DeallocationExecutor; +import org.iobserve.execution.stages.kubernetes.DeploymentExecutor; +import org.iobserve.execution.stages.kubernetes.UndeploymentExecutor; +import org.iobserve.stages.model.ModelFiles2ModelDirCollectorStage; +import org.iobserve.stages.source.SingleConnectionTcpReaderStage; + +import io.fabric8.kubernetes.api.model.extensions.Deployment; + +/** + * Configuration for the stages of the execution service. This configuration uses the kubernetes + * stages for the execution. + * + * @author Lars Bluemke + * + */ +public class KubernetesExecutionConfiguration extends Configuration { + + /** + * Creates a new configuration instance. + * + * @param executionPlanInputPort + * Input port for execution plan + * @param runtimeModelInputPort + * Input port for runtime model + * @param redeploymentModelInputPort + * Input port for redeployment model + * @param workingDirectory + * Working directory of execution + * @param runtimeModelDirectory + * Directory containing runtime models + * @param redeploymentModelDirectory + * Directory containing redeployment models + * @param correspondenceModelFile + * The correspondence model + * @param imageLocator + * Locator prefix for image + * @param subdomain + * Subdomain value of pods + * @param namespace + * Kubernetes namespace + */ + public KubernetesExecutionConfiguration(final int executionPlanInputPort, final int runtimeModelInputPort, + final int redeploymentModelInputPort, final File workingDirectory, final File runtimeModelDirectory, + final File redeploymentModelDirectory, final File correspondenceModelFile, final String imageLocator, + final String subdomain, final String namespace) { + + final SingleConnectionTcpReaderStage executionPlanReader = new SingleConnectionTcpReaderStage( + executionPlanInputPort, workingDirectory); + final SingleConnectionTcpReaderStage runtimeModelReader = new SingleConnectionTcpReaderStage( + runtimeModelInputPort, runtimeModelDirectory); + final SingleConnectionTcpReaderStage redeploymentModelReader = new SingleConnectionTcpReaderStage( + redeploymentModelInputPort, redeploymentModelDirectory); + final ModelFiles2ModelDirCollectorStage runtimeModelCollector = new ModelFiles2ModelDirCollectorStage(); + final ModelFiles2ModelDirCollectorStage redeploymentModelCollector = new ModelFiles2ModelDirCollectorStage(); + final ModelCollector modelCollector = new ModelCollector(); + final ExecutionPlanDeserialization executionPlanDeserializaton = new ExecutionPlanDeserialization(); + final ExecutionPlan2AtomicActions executionPlan2AtomicActions = new ExecutionPlan2AtomicActions(); + + final Map podsToDeploy = new HashMap<>(); + final DeploymentExecutor kubernetesDeploymentExecutor = new DeploymentExecutor(podsToDeploy, + correspondenceModelFile, namespace); + final UndeploymentExecutor kubernetesUndeploymentExecutor = new UndeploymentExecutor(namespace); + final AllocationExecutor kubernetesAllocationExecutor = new AllocationExecutor(imageLocator, subdomain, + podsToDeploy); + final DeallocationExecutor kubernetesDeallocationExecutor = new DeallocationExecutor(namespace); + final AtomicActionExecution atomicActionExecution = new AtomicActionExecution(kubernetesDeploymentExecutor, + kubernetesUndeploymentExecutor, null, null, null, null, null, kubernetesAllocationExecutor, + kubernetesDeallocationExecutor, null, null); + + this.connectPorts(runtimeModelReader.getOutputPort(), runtimeModelCollector.getInputPort()); + this.connectPorts(redeploymentModelReader.getOutputPort(), redeploymentModelCollector.getInputPort()); + this.connectPorts(executionPlanReader.getOutputPort(), modelCollector.getExecutionPlanInputPort()); + this.connectPorts(runtimeModelCollector.getOutputPort(), modelCollector.getRuntimeModelInputPort()); + this.connectPorts(redeploymentModelCollector.getOutputPort(), modelCollector.getRedeploymentModelInputPort()); + this.connectPorts(modelCollector.getOutputPort(), executionPlanDeserializaton.getInputPort()); + this.connectPorts(executionPlanDeserializaton.getOutputPort(), executionPlan2AtomicActions.getInputPort()); + this.connectPorts(executionPlan2AtomicActions.getOutputPort(), atomicActionExecution.getInputPort()); + + modelCollector.declareActive(); + } +} diff --git a/execution/src/main/java/org/iobserve/execution/stages/kubernetes/AllocationExecutor.java b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/AllocationExecutor.java new file mode 100644 index 00000000..85868dfd --- /dev/null +++ b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/AllocationExecutor.java @@ -0,0 +1,149 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.execution.stages.kubernetes; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.emf.common.util.EList; +import org.iobserve.adaptation.executionplan.AllocateNodeAction; +import org.palladiosimulator.pcm.resourceenvironment.HDDProcessingResourceSpecification; +import org.palladiosimulator.pcm.resourceenvironment.ProcessingResourceSpecification; +import org.palladiosimulator.pcm.resourceenvironment.ResourceContainer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.fabric8.kubernetes.api.model.extensions.Deployment; +import io.fabric8.kubernetes.api.model.extensions.DeploymentBuilder; + +/** + * Allocates a pod with kubernetes. Note that creating a pod with kubernetes immediately deploys an + * instance of that pod. Thus, creating a pod resembles an allocation and a deployment. + * Therefore we only create a pods specification here and leave the pod's actual creation to the + * {@link DeploymentExecutor}. + * + * @author Lars Bluemke + * + */ +public class AllocationExecutor extends AbstractExecutor { + private static final String API_VERSION = "extensions/v1beta1"; + private static final String PROCESSINGRATE_LABEL_KEY = "processingRate"; + private static final String HDDREADRATE_LABEL_KEY = "hddReadProcessingRate"; + private static final String HDDWRITERATE_LABEL_KEY = "hddWriteProcessingRate"; + private static final String COMPONENT_LABEL_KEY = "component"; + private static final Logger LOGGER = LoggerFactory.getLogger(AllocationExecutor.class); + + private final String imageLocator; + private final String subdomain; + private final Map podsToDeploy; + + /** + * + * @param imageLocator + * Image location + * @param subdomain + * Subdomain value + * @param podsToDeploy + * Map containing blueprints for pods to deploy + */ + public AllocationExecutor(final String imageLocator, final String subdomain, + final Map podsToDeploy) { + this.imageLocator = imageLocator; + this.subdomain = subdomain; + this.podsToDeploy = podsToDeploy; + } + + @Override + public void execute(final AllocateNodeAction action) { + final ResourceContainer resourceContainer = action.getTargetResourceContainer(); + final String rcName = this.normalizeComponentName(resourceContainer.getEntityName()); + + final Map labels = this.computeDeploymentLabels(resourceContainer); + + // Build deployment blueprint + final Deployment podDeployment = new DeploymentBuilder() // + /**/ .withApiVersion(AllocationExecutor.API_VERSION) // + /**/ .withKind("Deployment") // + /**/ .withNewMetadata() // + /*----*/ .withLabels(labels) // + /*----*/ .withName(rcName) // + /**/ .endMetadata() // + /**/ .withNewSpec() // + /*----*/ .withReplicas(1) // + /*----*/ .withNewSelector() // + /*--------*/ .addToMatchLabels(AllocationExecutor.COMPONENT_LABEL_KEY, rcName) // + /*----*/ .endSelector() // + /*----*/ .withNewTemplate() // + /*--------*/ .withNewMetadata() // + /*------------*/ .addToLabels(AllocationExecutor.COMPONENT_LABEL_KEY, rcName) // + /*------------*/ .withName(rcName) // + /*--------*/ .endMetadata() // + /*--------*/ .withNewSpec() // + /*------------*/ .withHostname(rcName) // + /*------------*/ .withSubdomain(this.subdomain) // + /*------------*/ .addNewContainer() // + /*---------------- Image and name are inserted at deployment */ + /*----------------*/ .withImage(this.imageLocator) // + /*----------------*/ .withName("") // + /*----------------*/ .withNewResources() // + /*----------------*/ .endResources() // + /*----------------*/ .addNewEnv() // + /*--------------------*/ .withName("LOGGER") // + /*--------------------*/ .withValue("%LOGGER%") // + /*----------------*/ .endEnv() // + /*------------*/ .endContainer() // + /*--------*/ .endSpec() // + /*----*/ .endTemplate() // + /**/ .endSpec() // + .build(); + + this.podsToDeploy.put(rcName, podDeployment); + + if (AllocationExecutor.LOGGER.isDebugEnabled()) { + AllocationExecutor.LOGGER + .debug("Created blueprint for pod deployment " + podDeployment.getMetadata().getName()); + } + } + + /** + * Computes deployment labels for a resource container. + * + * @param resourceContainer + * The resource container + * @return A map containing the computed labels + */ + private Map computeDeploymentLabels(final ResourceContainer resourceContainer) { + final EList specs = resourceContainer + .getActiveResourceSpecifications_ResourceContainer(); + final EList hddSpecs = resourceContainer.getHddResourceSpecifications(); + final Map labels = new HashMap<>(); + + // Only first specification object and only processing rates used so far + if (!specs.isEmpty()) { + labels.put(AllocationExecutor.PROCESSINGRATE_LABEL_KEY, + specs.get(0).getProcessingRate_ProcessingResourceSpecification().getSpecification()); + } + + if (!hddSpecs.isEmpty()) { + labels.put(AllocationExecutor.HDDREADRATE_LABEL_KEY, + hddSpecs.get(0).getReadProcessingRate().getSpecification()); + labels.put(AllocationExecutor.HDDWRITERATE_LABEL_KEY, + hddSpecs.get(0).getWriteProcessingRate().getSpecification()); + } + + return labels; + } +} diff --git a/execution/src/main/java/org/iobserve/execution/stages/kubernetes/DeallocationExecutor.java b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/DeallocationExecutor.java new file mode 100644 index 00000000..b75f1f4a --- /dev/null +++ b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/DeallocationExecutor.java @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.execution.stages.kubernetes; + +import org.iobserve.adaptation.executionplan.DeallocateNodeAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.fabric8.kubernetes.client.DefaultKubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClient; + +/** + * Deallocates a pod with kubernetes by deleting the pod. + * + * @author Lars Bluemke + * + */ +public class DeallocationExecutor extends AbstractExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(DeallocationExecutor.class); + + private final String namespace; + + /** + * Creates a new deallocation executor. + * + * @param namespace + * Kubernetes namespace + */ + public DeallocationExecutor(final String namespace) { + this.namespace = namespace; + } + + @Override + public void execute(final DeallocateNodeAction action) { + final KubernetesClient client = new DefaultKubernetesClient(); + final String rcName = this.normalizeComponentName(action.getTargetResourceContainer().getEntityName()); + + client.extensions().deployments().inNamespace(this.namespace).withName(rcName).delete(); + client.close(); + + if (DeallocationExecutor.LOGGER.isDebugEnabled()) { + DeallocationExecutor.LOGGER.debug("Successfully deleted pod deployment with name " + rcName); + } + } + +} diff --git a/execution/src/main/java/org/iobserve/execution/stages/kubernetes/DeploymentExecutor.java b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/DeploymentExecutor.java new file mode 100644 index 00000000..72e34795 --- /dev/null +++ b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/DeploymentExecutor.java @@ -0,0 +1,153 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.execution.stages.kubernetes; + +import java.io.File; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.iobserve.adaptation.executionplan.DeployComponentAction; +import org.iobserve.model.correspondence.AbstractEntry; +import org.iobserve.model.correspondence.AssemblyEntry; +import org.iobserve.model.correspondence.CorrespondenceModel; +import org.iobserve.model.correspondence.CorrespondencePackage; +import org.iobserve.model.persistence.file.FileModelHandler; +import org.palladiosimulator.pcm.core.composition.AssemblyContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.fabric8.kubernetes.api.model.extensions.Deployment; +import io.fabric8.kubernetes.client.DefaultKubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClient; + +/** + * Deploys a component instance with kubernetes. If the pod is already running this is done by + * incrementing its number of replicas. In case it is the first instance of this particular pod this + * may also require the creation of a new pod from its specifications as mentioned in + * {@link AllocationExecutor}. + * + * @author Lars Bluemke + * + */ +public class DeploymentExecutor extends AbstractExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(DeploymentExecutor.class); + + private final Map podsToDeploy; + private final File correspondenceModelFile; + private final String namespace; + + // TODO is this the correct location for the executor's resourceSet + private final ResourceSet resourceSet = new ResourceSetImpl(); + + /** + * Creates a new deployment executor. + * + * @param podsToDeploy + * Blueprints of pods to deploy + * @param correspondenceModelFile + * The correspondence model + * @param namespace + * Kubernetes namespace + */ + public DeploymentExecutor(final Map podsToDeploy, final File correspondenceModelFile, + final String namespace) { + this.podsToDeploy = podsToDeploy; + this.correspondenceModelFile = correspondenceModelFile; + this.namespace = namespace; + } + + @Override + public void execute(final DeployComponentAction action) { + // Can't be loaded earlier because it references the other models received via TCP + final CorrespondenceModel correspondenceModel = new FileModelHandler(this.resourceSet, + CorrespondencePackage.eINSTANCE) + .load(URI.createFileURI(this.correspondenceModelFile.getAbsolutePath())); + final KubernetesClient client = new DefaultKubernetesClient(); + final String rcName = this.normalizeComponentName( + action.getTargetAllocationContext().getResourceContainer_AllocationContext().getEntityName()); + final Deployment deployment = client.extensions().deployments().inNamespace(this.namespace).withName(rcName) + .get(); + final AssemblyContext targetAssemblyContext = action.getTargetAllocationContext() + .getAssemblyContext_AllocationContext(); + final String imageName = this.getImageName(correspondenceModel, targetAssemblyContext); + + if (deployment != null) { + // Increase number of replicas if pod is already deployed... + final int replicas = deployment.getSpec().getReplicas(); + deployment.getSpec().setReplicas(replicas + 1); + client.extensions().deployments().inNamespace(this.namespace).withName(rcName).replace(deployment); + + if (DeploymentExecutor.LOGGER.isDebugEnabled()) { + DeploymentExecutor.LOGGER.debug( + "Scaled pod deployment of " + deployment.getMetadata().getName() + " to " + (replicas + 1)); + } + } else { + // ... deploy new pod if this is not the case + final Deployment newDeployment = this.podsToDeploy.get(rcName); + final String imageLocator = newDeployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .getImage(); + + newDeployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .setImage(imageLocator + "/" + imageName); + newDeployment.getSpec().getTemplate().getSpec().getContainers().get(0) + .setName(this.normalizeComponentName(targetAssemblyContext.getEntityName())); + + client.extensions().deployments().inNamespace(this.namespace).create(newDeployment); + + if (DeploymentExecutor.LOGGER.isDebugEnabled()) { + DeploymentExecutor.LOGGER.debug("Image set to " + imageLocator + "/" + imageName); + DeploymentExecutor.LOGGER.debug("Created new pod deployment " + newDeployment.getMetadata().getName()); + } + } + + // Wait until deployed instance is ready + while (!client.extensions().deployments().inNamespace(this.namespace).withName(rcName).isReady()) { + if (DeploymentExecutor.LOGGER.isDebugEnabled()) { + DeploymentExecutor.LOGGER.debug(rcName + " is not ready yet."); + } + } + + client.close(); + } + + /** + * Gets the image name from the correspondence model. + * + * @param correspondenceModel + * The correspondence model containing the image name + * @param targetAssemblyContext + * The assembly context whose image name is required + * @return The image name + */ + private String getImageName(final CorrespondenceModel correspondenceModel, + final AssemblyContext targetAssemblyContext) { + String imageName = ""; + + for (final AbstractEntry e : correspondenceModel.getParts().get(0).getEntries()) { + if (e instanceof AssemblyEntry) { + final AssemblyEntry assEntry = (AssemblyEntry) e; + + if (assEntry.getAssembly().getId().equals(targetAssemblyContext.getId())) { + imageName = assEntry.getImplementationId(); + } + } + } + + return imageName; + } +} diff --git a/execution/src/main/java/org/iobserve/execution/stages/kubernetes/UndeploymentExecutor.java b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/UndeploymentExecutor.java new file mode 100644 index 00000000..6484333f --- /dev/null +++ b/execution/src/main/java/org/iobserve/execution/stages/kubernetes/UndeploymentExecutor.java @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.execution.stages.kubernetes; + +import org.iobserve.adaptation.executionplan.UndeployComponentAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.fabric8.kubernetes.api.model.extensions.Deployment; +import io.fabric8.kubernetes.client.DefaultKubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClient; + +/** + * Undeployment with kubernetes by decrementing the pod's number of replicas. + * + * @author Lars Bluemke + * + */ +public class UndeploymentExecutor extends AbstractExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(UndeploymentExecutor.class); + + private final String namespace; + + /** + * Creates a new executor for undeployments. + * + * @param namespace + * Kubernetes namespace + */ + public UndeploymentExecutor(final String namespace) { + this.namespace = namespace; + } + + @Override + public void execute(final UndeployComponentAction action) { + final KubernetesClient client = new DefaultKubernetesClient(); + final String rcName = this.normalizeComponentName( + action.getTargetAllocationContext().getResourceContainer_AllocationContext().getEntityName()); + final Deployment deployment = client.extensions().deployments().inNamespace(this.namespace).withName(rcName) + .get(); + final int replicas = deployment.getSpec().getReplicas(); + + // Note: Decrementing to 0 deletes all pods but not the deployment in kubernetes. The + // deployment is deleted in the DeallocationExecutor. + if (replicas > 0) { + deployment.getSpec().setReplicas(replicas - 1); + client.extensions().deployments().inNamespace(this.namespace).withName(rcName).replace(deployment); + } + + client.close(); + + if (UndeploymentExecutor.LOGGER.isDebugEnabled()) { + UndeploymentExecutor.LOGGER + .debug("Scaled pod deployment of " + deployment.getMetadata().getName() + " to " + (replicas - 1)); + } + } + +} diff --git a/model/storage-example.storage b/model/storage-example.storage new file mode 100644 index 00000000..e92a6ab7 --- /dev/null +++ b/model/storage-example.storage @@ -0,0 +1,14 @@ + + + label 1 + label 2 + label 3 + + + + + + + + + diff --git a/monitoring/src/main/java/org/iobserve/monitoring/probe/servlet/AccessControlFilter.java b/monitoring/src/main/java/org/iobserve/monitoring/probe/servlet/AccessControlFilter.java new file mode 100644 index 00000000..6d135e70 --- /dev/null +++ b/monitoring/src/main/java/org/iobserve/monitoring/probe/servlet/AccessControlFilter.java @@ -0,0 +1,122 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.monitoring.probe.servlet; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import kieker.monitoring.core.controller.IMonitoringController; +import kieker.monitoring.core.controller.MonitoringController; +import kieker.monitoring.core.registry.SessionRegistry; +import kieker.monitoring.probe.IMonitoringProbe; + +/** + * For each incoming request via {@link #doFilter(ServletRequest, ServletResponse, FilterChain)}, + * this class (i) registers session and trace information into the thread-local data structures + * {@link SessionRegistry} and {@link kieker.monitoring.core.registry.TraceRegistry} accessible to + * other probes in the control-flow of this request, (ii) executes the given {@link FilterChain} and + * subsequently (iii) unregisters the thread-local data. If configured in the {@link FilterConfig} + * (see below), the execution of the {@link #doFilter(ServletRequest, ServletResponse, FilterChain)} + * method is also part of the trace and logged to the {@link IMonitoringController} (note that this + * is the default behavior when no property is found). + * + * The filter can be integrated into the web.xml as follows: + * + *
+ * {@code
+ * 
+ *   accessControlFilter
+ *   org.spp.iobserve.monitoring.probe.servlet.AccessControlFilter
+ * 
+ * 
+ *   accessControlFilter
+ *   /*
+ * 
+ * }
+ * 
+ * + * @author Reiner Jung + * @since 0.0.2 + */ +public class AccessControlFilter implements Filter, IMonitoringProbe { + /** constant for a property name. */ + public static final String CONFIG_PROPERTY_NAME_LOG_FILTER_EXECUTION = "logFilterExecution"; + + /** Kieker monitoring controller. */ + protected static final IMonitoringController CTRLINST = MonitoringController.getInstance(); + + /** Host name of the host the code is running on. */ + protected static final String VM_NAME = SessionAndTraceRegistrationPayloadFilter.CTRLINST.getHostname(); + + @Override + public void init(final FilterConfig filterConfig) throws ServletException { + // no parameters required + } + + @Override + public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) + throws IOException, ServletException { + if (AccessControlFilter.CTRLINST.isMonitoringEnabled()) { + if (request instanceof HttpServletRequest) { + final String remoteAddr = request.getRemoteAddr(); + if (this.isInWhiteList(remoteAddr, this.computeLocationId((HttpServletRequest) request))) { + chain.doFilter(request, response); + } else { + ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_FORBIDDEN); + chain.doFilter(request, response); + } + } + } else { + chain.doFilter(request, response); + } + } + + private String computeLocationId(final HttpServletRequest request) { + String parameters = null; + final Enumeration names = request.getParameterNames(); + while (names.hasMoreElements()) { + if (parameters == null) { + parameters = names.nextElement(); + } else { + parameters += ", " + names.nextElement(); + } + } + + return String.format("%s %s %s (%s)", request.getRequestURI(), parameters); + } + + private boolean isInWhiteList(final String remoteAddr, final String locationId) { + final Map> parameters = AccessControlFilter.CTRLINST.getParameters(locationId); + return parameters.get("whitelist").contains(remoteAddr); + } + + @Override + public void destroy() { + // by default, we do nothing here. Extending classes may override this method + } + +} diff --git a/planning.systemadaptation/src/gen/java/org/iobserve/adaptation/executionplan/impl/ExecutionplanPackageImpl.java b/planning.systemadaptation/src/gen/java/org/iobserve/adaptation/executionplan/impl/ExecutionplanPackageImpl.java new file mode 100644 index 00000000..9518868f --- /dev/null +++ b/planning.systemadaptation/src/gen/java/org/iobserve/adaptation/executionplan/impl/ExecutionplanPackageImpl.java @@ -0,0 +1,619 @@ +/** + */ +package org.iobserve.adaptation.executionplan.impl; + +import de.uka.ipd.sdq.identifier.IdentifierPackage; + +import de.uka.ipd.sdq.probfunction.ProbfunctionPackage; + +import de.uka.ipd.sdq.stoex.StoexPackage; + +import de.uka.ipd.sdq.units.UnitsPackage; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; + +import org.eclipse.emf.ecore.impl.EPackageImpl; + +import org.iobserve.adaptation.executionplan.AllocateNodeAction; +import org.iobserve.adaptation.executionplan.AssemblyContextAction; +import org.iobserve.adaptation.executionplan.AtomicAction; +import org.iobserve.adaptation.executionplan.BlockRequestsToComponentAction; +import org.iobserve.adaptation.executionplan.ConnectComponentAction; +import org.iobserve.adaptation.executionplan.ConnectNodeAction; +import org.iobserve.adaptation.executionplan.DeallocateNodeAction; +import org.iobserve.adaptation.executionplan.DeployComponentAction; +import org.iobserve.adaptation.executionplan.DisconnectComponentAction; +import org.iobserve.adaptation.executionplan.DisconnectNodeAction; +import org.iobserve.adaptation.executionplan.ExecutionPlan; +import org.iobserve.adaptation.executionplan.ExecutionplanFactory; +import org.iobserve.adaptation.executionplan.ExecutionplanPackage; +import org.iobserve.adaptation.executionplan.FinishComponentAction; +import org.iobserve.adaptation.executionplan.MigrateComponentStateAction; +import org.iobserve.adaptation.executionplan.ResourceContainerAction; +import org.iobserve.adaptation.executionplan.UndeployComponentAction; + +import org.palladiosimulator.pcm.PcmPackage; + +import org.palladiosimulator.pcm.allocation.AllocationPackage; + +import org.palladiosimulator.pcm.resourceenvironment.ResourceenvironmentPackage; + +/** + * + * An implementation of the model Package. + * + * @generated + */ +public class ExecutionplanPackageImpl extends EPackageImpl implements ExecutionplanPackage { + /** + * + * + * @generated + */ + private EClass executionPlanEClass = null; + + /** + * + * + * @generated + */ + private EClass atomicActionEClass = null; + + /** + * + * + * @generated + */ + private EClass assemblyContextActionEClass = null; + + /** + * + * + * @generated + */ + private EClass resourceContainerActionEClass = null; + + /** + * + * + * @generated + */ + private EClass deployComponentActionEClass = null; + + /** + * + * + * @generated + */ + private EClass undeployComponentActionEClass = null; + + /** + * + * + * @generated + */ + private EClass migrateComponentStateActionEClass = null; + + /** + * + * + * @generated + */ + private EClass connectComponentActionEClass = null; + + /** + * + * + * @generated + */ + private EClass blockRequestsToComponentActionEClass = null; + + /** + * + * + * @generated + */ + private EClass disconnectComponentActionEClass = null; + + /** + * + * + * @generated + */ + private EClass finishComponentActionEClass = null; + + /** + * + * + * @generated + */ + private EClass allocateNodeActionEClass = null; + + /** + * + * + * @generated + */ + private EClass deallocateNodeActionEClass = null; + + /** + * + * + * @generated + */ + private EClass connectNodeActionEClass = null; + + /** + * + * + * @generated + */ + private EClass disconnectNodeActionEClass = null; + + /** + * Creates an instance of the model Package, registered with + * {@link org.eclipse.emf.ecore.EPackage.Registry EPackage.Registry} by the package + * package URI value. + *

Note: the correct way to create the package is via the static + * factory method {@link #init init()}, which also performs + * initialization of the package, or returns the registered package, + * if one already exists. + * + * + * @see org.eclipse.emf.ecore.EPackage.Registry + * @see org.iobserve.adaptation.executionplan.ExecutionplanPackage#eNS_URI + * @see #init() + * @generated + */ + private ExecutionplanPackageImpl() { + super(eNS_URI, ExecutionplanFactory.eINSTANCE); + } + + /** + * + * + * @generated + */ + private static boolean isInited = false; + + /** + * Creates, registers, and initializes the Package for this model, and for any others upon which it depends. + * + *

This method is used to initialize {@link ExecutionplanPackage#eINSTANCE} when that field is accessed. + * Clients should not invoke it directly. Instead, they should simply access that field to obtain the package. + * + * + * @see #eNS_URI + * @see #createPackageContents() + * @see #initializePackageContents() + * @generated + */ + public static ExecutionplanPackage init() { + if (isInited) return (ExecutionplanPackage)EPackage.Registry.INSTANCE.getEPackage(ExecutionplanPackage.eNS_URI); + + // Obtain or create and register package + ExecutionplanPackageImpl theExecutionplanPackage = (ExecutionplanPackageImpl)(EPackage.Registry.INSTANCE.get(eNS_URI) instanceof ExecutionplanPackageImpl ? EPackage.Registry.INSTANCE.get(eNS_URI) : new ExecutionplanPackageImpl()); + + isInited = true; + + // Initialize simple dependencies + IdentifierPackage.eINSTANCE.eClass(); + PcmPackage.eINSTANCE.eClass(); + ProbfunctionPackage.eINSTANCE.eClass(); + StoexPackage.eINSTANCE.eClass(); + UnitsPackage.eINSTANCE.eClass(); + + // Create package meta-data objects + theExecutionplanPackage.createPackageContents(); + + // Initialize created meta-data + theExecutionplanPackage.initializePackageContents(); + + // Mark meta-data to indicate it can't be changed + theExecutionplanPackage.freeze(); + + + // Update the registry and return the package + EPackage.Registry.INSTANCE.put(ExecutionplanPackage.eNS_URI, theExecutionplanPackage); + return theExecutionplanPackage; + } + + /** + * + * + * @generated + */ + public EClass getExecutionPlan() { + return executionPlanEClass; + } + + /** + * + * + * @generated + */ + public EReference getExecutionPlan_Actions() { + return (EReference)executionPlanEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EClass getAtomicAction() { + return atomicActionEClass; + } + + /** + * + * + * @generated + */ + public EClass getAssemblyContextAction() { + return assemblyContextActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getAssemblyContextAction_TargetAllocationContext() { + return (EReference)assemblyContextActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EClass getResourceContainerAction() { + return resourceContainerActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getResourceContainerAction_TargetResourceContainer() { + return (EReference)resourceContainerActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EClass getDeployComponentAction() { + return deployComponentActionEClass; + } + + /** + * + * + * @generated + */ + public EClass getUndeployComponentAction() { + return undeployComponentActionEClass; + } + + /** + * + * + * @generated + */ + public EClass getMigrateComponentStateAction() { + return migrateComponentStateActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getMigrateComponentStateAction_SourceAllocationContext() { + return (EReference)migrateComponentStateActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EClass getConnectComponentAction() { + return connectComponentActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getConnectComponentAction_TargetProvidingAllocationContexts() { + return (EReference)connectComponentActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EReference getConnectComponentAction_TargetRequiringAllocationContexts() { + return (EReference)connectComponentActionEClass.getEStructuralFeatures().get(1); + } + + /** + * + * + * @generated + */ + public EClass getBlockRequestsToComponentAction() { + return blockRequestsToComponentActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getBlockRequestsToComponentAction_TargetRequiringAllocationContexts() { + return (EReference)blockRequestsToComponentActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EClass getDisconnectComponentAction() { + return disconnectComponentActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getDisconnectComponentAction_TargetProvidingAllocationContexts() { + return (EReference)disconnectComponentActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EReference getDisconnectComponentAction_TargetRequiringAllocationContexts() { + return (EReference)disconnectComponentActionEClass.getEStructuralFeatures().get(1); + } + + /** + * + * + * @generated + */ + public EClass getFinishComponentAction() { + return finishComponentActionEClass; + } + + /** + * + * + * @generated + */ + public EClass getAllocateNodeAction() { + return allocateNodeActionEClass; + } + + /** + * + * + * @generated + */ + public EClass getDeallocateNodeAction() { + return deallocateNodeActionEClass; + } + + /** + * + * + * @generated + */ + public EClass getConnectNodeAction() { + return connectNodeActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getConnectNodeAction_TargetConnectors() { + return (EReference)connectNodeActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public EClass getDisconnectNodeAction() { + return disconnectNodeActionEClass; + } + + /** + * + * + * @generated + */ + public EReference getDisconnectNodeAction_TargetConnectors() { + return (EReference)disconnectNodeActionEClass.getEStructuralFeatures().get(0); + } + + /** + * + * + * @generated + */ + public ExecutionplanFactory getExecutionplanFactory() { + return (ExecutionplanFactory)getEFactoryInstance(); + } + + /** + * + * + * @generated + */ + private boolean isCreated = false; + + /** + * Creates the meta-model objects for the package. This method is + * guarded to have no affect on any invocation but its first. + * + * + * @generated + */ + public void createPackageContents() { + if (isCreated) return; + isCreated = true; + + // Create classes and their features + executionPlanEClass = createEClass(EXECUTION_PLAN); + createEReference(executionPlanEClass, EXECUTION_PLAN__ACTIONS); + + atomicActionEClass = createEClass(ATOMIC_ACTION); + + assemblyContextActionEClass = createEClass(ASSEMBLY_CONTEXT_ACTION); + createEReference(assemblyContextActionEClass, ASSEMBLY_CONTEXT_ACTION__TARGET_ALLOCATION_CONTEXT); + + resourceContainerActionEClass = createEClass(RESOURCE_CONTAINER_ACTION); + createEReference(resourceContainerActionEClass, RESOURCE_CONTAINER_ACTION__TARGET_RESOURCE_CONTAINER); + + deployComponentActionEClass = createEClass(DEPLOY_COMPONENT_ACTION); + + undeployComponentActionEClass = createEClass(UNDEPLOY_COMPONENT_ACTION); + + migrateComponentStateActionEClass = createEClass(MIGRATE_COMPONENT_STATE_ACTION); + createEReference(migrateComponentStateActionEClass, MIGRATE_COMPONENT_STATE_ACTION__SOURCE_ALLOCATION_CONTEXT); + + connectComponentActionEClass = createEClass(CONNECT_COMPONENT_ACTION); + createEReference(connectComponentActionEClass, CONNECT_COMPONENT_ACTION__TARGET_PROVIDING_ALLOCATION_CONTEXTS); + createEReference(connectComponentActionEClass, CONNECT_COMPONENT_ACTION__TARGET_REQUIRING_ALLOCATION_CONTEXTS); + + blockRequestsToComponentActionEClass = createEClass(BLOCK_REQUESTS_TO_COMPONENT_ACTION); + createEReference(blockRequestsToComponentActionEClass, BLOCK_REQUESTS_TO_COMPONENT_ACTION__TARGET_REQUIRING_ALLOCATION_CONTEXTS); + + disconnectComponentActionEClass = createEClass(DISCONNECT_COMPONENT_ACTION); + createEReference(disconnectComponentActionEClass, DISCONNECT_COMPONENT_ACTION__TARGET_PROVIDING_ALLOCATION_CONTEXTS); + createEReference(disconnectComponentActionEClass, DISCONNECT_COMPONENT_ACTION__TARGET_REQUIRING_ALLOCATION_CONTEXTS); + + finishComponentActionEClass = createEClass(FINISH_COMPONENT_ACTION); + + allocateNodeActionEClass = createEClass(ALLOCATE_NODE_ACTION); + + deallocateNodeActionEClass = createEClass(DEALLOCATE_NODE_ACTION); + + connectNodeActionEClass = createEClass(CONNECT_NODE_ACTION); + createEReference(connectNodeActionEClass, CONNECT_NODE_ACTION__TARGET_CONNECTORS); + + disconnectNodeActionEClass = createEClass(DISCONNECT_NODE_ACTION); + createEReference(disconnectNodeActionEClass, DISCONNECT_NODE_ACTION__TARGET_CONNECTORS); + } + + /** + * + * + * @generated + */ + private boolean isInitialized = false; + + /** + * Complete the initialization of the package and its meta-model. This + * method is guarded to have no affect on any invocation but its first. + * + * + * @generated + */ + public void initializePackageContents() { + if (isInitialized) return; + isInitialized = true; + + // Initialize package + setName(eNAME); + setNsPrefix(eNS_PREFIX); + setNsURI(eNS_URI); + + // Obtain other dependent packages + AllocationPackage theAllocationPackage = (AllocationPackage)EPackage.Registry.INSTANCE.getEPackage(AllocationPackage.eNS_URI); + ResourceenvironmentPackage theResourceenvironmentPackage = (ResourceenvironmentPackage)EPackage.Registry.INSTANCE.getEPackage(ResourceenvironmentPackage.eNS_URI); + + // Create type parameters + + // Set bounds for type parameters + + // Add supertypes to classes + assemblyContextActionEClass.getESuperTypes().add(this.getAtomicAction()); + resourceContainerActionEClass.getESuperTypes().add(this.getAtomicAction()); + deployComponentActionEClass.getESuperTypes().add(this.getAssemblyContextAction()); + undeployComponentActionEClass.getESuperTypes().add(this.getAssemblyContextAction()); + migrateComponentStateActionEClass.getESuperTypes().add(this.getAssemblyContextAction()); + connectComponentActionEClass.getESuperTypes().add(this.getAssemblyContextAction()); + blockRequestsToComponentActionEClass.getESuperTypes().add(this.getAssemblyContextAction()); + disconnectComponentActionEClass.getESuperTypes().add(this.getAssemblyContextAction()); + finishComponentActionEClass.getESuperTypes().add(this.getAssemblyContextAction()); + allocateNodeActionEClass.getESuperTypes().add(this.getResourceContainerAction()); + deallocateNodeActionEClass.getESuperTypes().add(this.getResourceContainerAction()); + connectNodeActionEClass.getESuperTypes().add(this.getResourceContainerAction()); + disconnectNodeActionEClass.getESuperTypes().add(this.getResourceContainerAction()); + + // Initialize classes and features; add operations and parameters + initEClass(executionPlanEClass, ExecutionPlan.class, "ExecutionPlan", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getExecutionPlan_Actions(), this.getAtomicAction(), null, "actions", null, 0, -1, ExecutionPlan.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(atomicActionEClass, AtomicAction.class, "AtomicAction", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + + initEClass(assemblyContextActionEClass, AssemblyContextAction.class, "AssemblyContextAction", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getAssemblyContextAction_TargetAllocationContext(), theAllocationPackage.getAllocationContext(), null, "targetAllocationContext", null, 1, 1, AssemblyContextAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(resourceContainerActionEClass, ResourceContainerAction.class, "ResourceContainerAction", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getResourceContainerAction_TargetResourceContainer(), theResourceenvironmentPackage.getResourceContainer(), null, "targetResourceContainer", null, 1, 1, ResourceContainerAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(deployComponentActionEClass, DeployComponentAction.class, "DeployComponentAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + + initEClass(undeployComponentActionEClass, UndeployComponentAction.class, "UndeployComponentAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + + initEClass(migrateComponentStateActionEClass, MigrateComponentStateAction.class, "MigrateComponentStateAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getMigrateComponentStateAction_SourceAllocationContext(), theAllocationPackage.getAllocationContext(), null, "sourceAllocationContext", null, 1, 1, MigrateComponentStateAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(connectComponentActionEClass, ConnectComponentAction.class, "ConnectComponentAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getConnectComponentAction_TargetProvidingAllocationContexts(), theAllocationPackage.getAllocationContext(), null, "targetProvidingAllocationContexts", null, 0, -1, ConnectComponentAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + initEReference(getConnectComponentAction_TargetRequiringAllocationContexts(), theAllocationPackage.getAllocationContext(), null, "targetRequiringAllocationContexts", null, 0, -1, ConnectComponentAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(blockRequestsToComponentActionEClass, BlockRequestsToComponentAction.class, "BlockRequestsToComponentAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getBlockRequestsToComponentAction_TargetRequiringAllocationContexts(), theAllocationPackage.getAllocationContext(), null, "targetRequiringAllocationContexts", null, 0, -1, BlockRequestsToComponentAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(disconnectComponentActionEClass, DisconnectComponentAction.class, "DisconnectComponentAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getDisconnectComponentAction_TargetProvidingAllocationContexts(), theAllocationPackage.getAllocationContext(), null, "targetProvidingAllocationContexts", null, 0, -1, DisconnectComponentAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + initEReference(getDisconnectComponentAction_TargetRequiringAllocationContexts(), theAllocationPackage.getAllocationContext(), null, "targetRequiringAllocationContexts", null, 0, -1, DisconnectComponentAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(finishComponentActionEClass, FinishComponentAction.class, "FinishComponentAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + + initEClass(allocateNodeActionEClass, AllocateNodeAction.class, "AllocateNodeAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + + initEClass(deallocateNodeActionEClass, DeallocateNodeAction.class, "DeallocateNodeAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + + initEClass(connectNodeActionEClass, ConnectNodeAction.class, "ConnectNodeAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getConnectNodeAction_TargetConnectors(), theResourceenvironmentPackage.getLinkingResource(), null, "targetConnectors", null, 0, -1, ConnectNodeAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + initEClass(disconnectNodeActionEClass, DisconnectNodeAction.class, "DisconnectNodeAction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); + initEReference(getDisconnectNodeAction_TargetConnectors(), theResourceenvironmentPackage.getLinkingResource(), null, "targetConnectors", null, 0, -1, DisconnectNodeAction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + + // Create resource + createResource(eNS_URI); + } + +} //ExecutionplanPackageImpl diff --git a/service.privacy.violation/src/main/java/org/iobserve/service/privacy/violation/PrivacyConfigurationsKeys.java b/service.privacy.violation/src/main/java/org/iobserve/service/privacy/violation/PrivacyConfigurationsKeys.java new file mode 100644 index 00000000..b7d7c29c --- /dev/null +++ b/service.privacy.violation/src/main/java/org/iobserve/service/privacy/violation/PrivacyConfigurationsKeys.java @@ -0,0 +1,41 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.service.privacy.violation; + +import org.iobserve.analysis.ConfigurationKeys; + +/** + * @author Reiner Jung + * + */ +public final class PrivacyConfigurationsKeys { + + public static final String PREFIX = ConfigurationKeys.PREFIX + "privacy."; + + public static final String ALARM_FILE_PATH = PrivacyConfigurationsKeys.PREFIX + "alarmFile"; + + public static final String WARNING_FILE_PATH = PrivacyConfigurationsKeys.PREFIX + "warningFile"; + + public static final String PROBE_CONNECTIONS_OUTPUTS = PrivacyConfigurationsKeys.PREFIX + "probeControls"; + + public static final String POLICY_PACKAGE_PREFIX = PrivacyConfigurationsKeys.PREFIX + "packagePrefix"; + + public static final String POLICY_LIST = PrivacyConfigurationsKeys.PREFIX + "policyList"; + + private PrivacyConfigurationsKeys() { + // empty, factory + } +} diff --git a/stages/src/main/java/org/iobserve/stages/model/DeserializePcmModelStage.java b/stages/src/main/java/org/iobserve/stages/model/DeserializePcmModelStage.java new file mode 100644 index 00000000..97660354 --- /dev/null +++ b/stages/src/main/java/org/iobserve/stages/model/DeserializePcmModelStage.java @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.stages.model; + +import java.io.File; + +import de.uka.ipd.sdq.dsexplore.qml.declarations.QMLDeclarations.QMLDeclarations; +import de.uka.ipd.sdq.dsexplore.qml.declarations.QMLDeclarations.QMLDeclarationsPackage; +import de.uka.ipd.sdq.pcm.cost.CostRepository; +import de.uka.ipd.sdq.pcm.cost.costPackage; +import de.uka.ipd.sdq.pcm.designdecision.DecisionSpace; +import de.uka.ipd.sdq.pcm.designdecision.designdecisionPackage; + +import teetime.stage.basic.AbstractTransformation; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.iobserve.model.persistence.file.FileModelHandler; +import org.palladiosimulator.pcm.allocation.Allocation; +import org.palladiosimulator.pcm.allocation.AllocationPackage; +import org.palladiosimulator.pcm.cloud.pcmcloud.cloudprofile.CloudProfile; +import org.palladiosimulator.pcm.cloud.pcmcloud.cloudprofile.CloudprofilePackage; +import org.palladiosimulator.pcm.repository.Repository; +import org.palladiosimulator.pcm.repository.RepositoryPackage; +import org.palladiosimulator.pcm.resourceenvironment.ResourceEnvironment; +import org.palladiosimulator.pcm.resourceenvironment.ResourceenvironmentPackage; +import org.palladiosimulator.pcm.system.System; +import org.palladiosimulator.pcm.system.SystemPackage; +import org.palladiosimulator.pcm.usagemodel.UsageModel; +import org.palladiosimulator.pcm.usagemodel.UsagemodelPackage; + +/** + * This stage gets a serialized PCM model's File and loads the model EObject from it. The EObject is + * provided via the stages output port. + * + * @author Lars Bluemke + * + */ +public class DeserializePcmModelStage extends AbstractTransformation { + + private final ResourceSet resourceSet = new ResourceSetImpl(); + + @Override + protected void execute(final File modelFile) throws Exception { + final String modelFileName = modelFile.getName(); + final String modelFileExtension = modelFileName.substring(modelFileName.lastIndexOf('.') + 1); + final EObject model; + + if (AllocationPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, AllocationPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (CloudprofilePackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, CloudprofilePackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (costPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, costPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (designdecisionPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, designdecisionPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (QMLDeclarationsPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, QMLDeclarationsPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (RepositoryPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, RepositoryPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (ResourceenvironmentPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, ResourceenvironmentPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (SystemPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, SystemPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else if (UsagemodelPackage.eNAME.equals(modelFileExtension)) { + model = new FileModelHandler(this.resourceSet, UsagemodelPackage.eINSTANCE) + .load(URI.createFileURI(modelFile.getAbsolutePath())); + } else { + throw new IllegalArgumentException("File extension does not look like a PCM model!"); + } + + this.getOutputPort().send(model); + } + +} diff --git a/stages/src/main/java/org/iobserve/stages/model/SerializePcmModelStage.java b/stages/src/main/java/org/iobserve/stages/model/SerializePcmModelStage.java new file mode 100644 index 00000000..c70c73ad --- /dev/null +++ b/stages/src/main/java/org/iobserve/stages/model/SerializePcmModelStage.java @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2018 iObserve Project (https://www.iobserve-devops.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package org.iobserve.stages.model; + +import java.io.File; + +import de.uka.ipd.sdq.dsexplore.qml.declarations.QMLDeclarations.QMLDeclarations; +import de.uka.ipd.sdq.dsexplore.qml.declarations.QMLDeclarations.QMLDeclarationsPackage; +import de.uka.ipd.sdq.pcm.cost.CostRepository; +import de.uka.ipd.sdq.pcm.cost.costPackage; +import de.uka.ipd.sdq.pcm.designdecision.DecisionSpace; +import de.uka.ipd.sdq.pcm.designdecision.designdecisionPackage; + +import teetime.stage.basic.AbstractTransformation; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.iobserve.model.persistence.file.FileModelHandler; +import org.palladiosimulator.pcm.allocation.Allocation; +import org.palladiosimulator.pcm.allocation.AllocationPackage; +import org.palladiosimulator.pcm.cloud.pcmcloud.cloudprofile.CloudProfile; +import org.palladiosimulator.pcm.cloud.pcmcloud.cloudprofile.CloudprofilePackage; +import org.palladiosimulator.pcm.repository.Repository; +import org.palladiosimulator.pcm.repository.RepositoryPackage; +import org.palladiosimulator.pcm.resourceenvironment.ResourceEnvironment; +import org.palladiosimulator.pcm.resourceenvironment.ResourceenvironmentPackage; +import org.palladiosimulator.pcm.system.System; +import org.palladiosimulator.pcm.system.SystemPackage; +import org.palladiosimulator.pcm.usagemodel.UsageModel; +import org.palladiosimulator.pcm.usagemodel.UsagemodelPackage; + +/** + * This stage gets a PCM model EObject and serializes it in a File. The file is provided via the + * stages output port. + * + * @author Lars Bluemke + * + */ +public class SerializePcmModelStage extends AbstractTransformation { + + private final File modelDirectory; + private final String modelName; + + /** + * Creates a new instance of this class. + * + * @param modelDirectory + * Directory for serialized models + * @param modelName + * Name for serialized models + */ + public SerializePcmModelStage(final File modelDirectory, final String modelName) { + this.modelDirectory = modelDirectory; + this.modelName = modelName; + } + + @Override + protected void execute(final EObject model) throws Exception { + final ResourceSet resourceSet = model.eResource().getResourceSet(); + final String filePathPrefix = this.modelDirectory.getAbsolutePath() + File.separator + this.modelName; + final String filePath; + + if (model instanceof Allocation) { + filePath = filePathPrefix + "." + AllocationPackage.eNAME; + new FileModelHandler(resourceSet, AllocationPackage.eINSTANCE) + .save(URI.createFileURI(filePath), (Allocation) model); + } else if (model instanceof CloudProfile) { + filePath = filePathPrefix + "." + CloudprofilePackage.eNAME; + new FileModelHandler(resourceSet, CloudprofilePackage.eINSTANCE) + .save(URI.createFileURI(filePath), (CloudProfile) model); + } else if (model instanceof CostRepository) { + filePath = filePathPrefix + "." + costPackage.eNAME; + new FileModelHandler(resourceSet, costPackage.eINSTANCE) + .save(URI.createFileURI(filePath), (CostRepository) model); + } else if (model instanceof DecisionSpace) { + filePath = filePathPrefix + "." + designdecisionPackage.eNAME; + new FileModelHandler(resourceSet, designdecisionPackage.eINSTANCE) + .save(URI.createFileURI(filePath), (DecisionSpace) model); + } else if (model instanceof QMLDeclarations) { + filePath = filePathPrefix + "." + QMLDeclarationsPackage.eNAME; + new FileModelHandler(resourceSet, QMLDeclarationsPackage.eINSTANCE) + .save(URI.createFileURI(filePath), (QMLDeclarations) model); + } else if (model instanceof Repository) { + filePath = filePathPrefix + "." + RepositoryPackage.eNAME; + new FileModelHandler(resourceSet, RepositoryPackage.eINSTANCE) + .save(URI.createFileURI(filePath), (Repository) model); + } else if (model instanceof ResourceEnvironment) { + filePath = filePathPrefix + "." + ResourceenvironmentPackage.eNAME; + new FileModelHandler(resourceSet, ResourceenvironmentPackage.eINSTANCE) + .save(URI.createFileURI(filePath), (ResourceEnvironment) model); + } else if (model instanceof System) { + filePath = filePathPrefix + "." + SystemPackage.eNAME; + new FileModelHandler(resourceSet, SystemPackage.eINSTANCE).save(URI.createFileURI(filePath), + (System) model); + } else if (model instanceof UsageModel) { + filePath = filePathPrefix + UsagemodelPackage.eNAME; + new FileModelHandler(resourceSet, UsagemodelPackage.eINSTANCE) + .save(URI.createFileURI(filePath), (UsageModel) model); + } else { + throw new IllegalArgumentException("The EObject passed to this stage must be a PCM model!"); + } + + this.getOutputPort().send(new File(filePath)); + } + +} diff --git a/stages/src/main/java/org/iobserve/utility/tcp/TcpProbeController.java b/stages/src/main/java/org/iobserve/utility/tcp/TcpProbeController.java index 57ddb59a..a1614cab 100644 --- a/stages/src/main/java/org/iobserve/utility/tcp/TcpProbeController.java +++ b/stages/src/main/java/org/iobserve/utility/tcp/TcpProbeController.java @@ -17,18 +17,22 @@ import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; import kieker.common.configuration.Configuration; import kieker.common.record.remotecontrol.ActivationEvent; +import kieker.common.record.remotecontrol.ActivationParameterEvent; import kieker.common.record.remotecontrol.DeactivationEvent; import kieker.common.record.remotecontrol.IRemoteControlEvent; +import kieker.common.record.remotecontrol.UpdateParameterEvent; import kieker.monitoring.writer.tcp.ConnectionTimeoutException; import kieker.monitoring.writer.tcp.SingleSocketTcpWriter; import org.iobserve.utility.tcp.events.AbstractTcpControlEvent; import org.iobserve.utility.tcp.events.TcpActivationControlEvent; -import org.iobserve.utility.tcp.events.TcpDeactivationEvent; +import org.iobserve.utility.tcp.events.TcpActivationParameterControlEvent; +import org.iobserve.utility.tcp.events.TcpDeactivationControlEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,8 +73,13 @@ public void controlProbe(final AbstractTcpControlEvent event) throws RemoteContr final String hostname = event.getHostname(); final String pattern = event.getPattern(); if (event instanceof TcpActivationControlEvent) { - this.activateMonitoredPattern(ip, port, hostname, pattern); - } else if (event instanceof TcpDeactivationEvent) { + if (event instanceof TcpActivationParameterControlEvent) { + this.activateParameterMonitoredPattern(ip, port, hostname, pattern, + ((TcpActivationParameterControlEvent) event).getParameters()); + } else { + this.activateMonitoredPattern(ip, port, hostname, pattern); + } + } else if (event instanceof TcpDeactivationControlEvent) { this.deactivateMonitoredPattern(ip, port, hostname, pattern); } else { if (TcpProbeController.LOGGER.isErrorEnabled()) { @@ -80,6 +89,31 @@ public void controlProbe(final AbstractTcpControlEvent event) throws RemoteContr } + /** + * Updates the given parameters for a probe. + * + * @param ip + * Address of the monitored application. + * @param port + * Port of the TCP controller. + * @param hostname + * The name of the component which is using this IP and port. + * @param pattern + * The pattern of the method that should is monitored. + * @param parameters + * The map of parameters to be set, the key is the name and the values the values for + * the parameter. + * @throws RemoteControlFailedException + * if the connection can not be established within a set timeout. + */ + public void updateProbeParameter(final String ip, final int port, final String hostname, final String pattern, + final Map> parameters) throws RemoteControlFailedException { + final String[] parameterNames = parameters.keySet().toArray(new String[0]); + final String[][] parameterArray = this.computeParameterArray(parameters); + + this.sendTcpCommand(ip, port, hostname, new UpdateParameterEvent(pattern, parameterNames, parameterArray)); + } + /** * Activates monitoring of a method (pattern) on one monitored application via TCP. * @@ -99,6 +133,32 @@ public void activateMonitoredPattern(final String ip, final int port, final Stri this.sendTcpCommand(ip, port, hostname, new ActivationEvent(pattern)); } + /** + * Activates monitoring of a method (pattern) on one monitored application via TCP and transfers + * parameter. + * + * @param ip + * Address of the monitored application. + * @param port + * Port of the TCP controller. + * @param hostname + * The name of the component which is using this IP and port. + * @param pattern + * The pattern of the method that should be monitored. + * @param parameters + * The map of parameters to be set, the key is the name and the values the values for + * the parameter. + * @throws RemoteControlFailedException + * if the connection can not be established within a set timeout. + */ + public void activateParameterMonitoredPattern(final String ip, final int port, final String hostname, + final String pattern, final Map> parameters) throws RemoteControlFailedException { + final String[] parameterNames = parameters.keySet().toArray(new String[0]); + final String[][] parameterArray = this.computeParameterArray(parameters); + + this.sendTcpCommand(ip, port, hostname, new ActivationParameterEvent(pattern, parameterNames, parameterArray)); + } + /** * Deactivates monitoring of a method (pattern) on one monitored application via TCP. * @@ -126,7 +186,7 @@ private void sendTcpCommand(final String ip, final int port, final String hostna TcpControlConnection currentConnection = this.knownAddresses.get(writerKey); // if host was never used or an other module was there before, create a new connection - if (currentConnection == null || currentConnection.getHostname() != hostname) { + if ((currentConnection == null) || (currentConnection.getHostname() != hostname)) { currentConnection = new TcpControlConnection(ip, port, hostname, this.createNewTcpWriter(ip, port)); this.knownAddresses.put(writerKey, currentConnection); } @@ -182,4 +242,17 @@ private SingleSocketTcpWriter createNewTcpWriter(final String hostname, final in public boolean isKnownHost(final String ip, final int port) { return this.knownAddresses.keySet().contains(ip + ":" + port); } + + private String[][] computeParameterArray(final Map> parameters) { + final String[] parameterNames = parameters.keySet().toArray(new String[0]); + + final int parameterLength = parameterNames.length; + final String[][] parameterArray = new String[parameterLength][]; + + for (int i = 0; i < parameterLength; i++) { + parameterArray[i] = (String[]) parameters.get(parameterNames[i]).toArray(); + } + return parameterArray; + } + } diff --git a/stages/src/test/java/org/iobserve/stages/test/utility/tcp/TcpProbeControllerTest.java b/stages/src/test/java/org/iobserve/stages/test/utility/tcp/TcpProbeControllerTest.java index 90f9d47a..de6cc555 100644 --- a/stages/src/test/java/org/iobserve/stages/test/utility/tcp/TcpProbeControllerTest.java +++ b/stages/src/test/java/org/iobserve/stages/test/utility/tcp/TcpProbeControllerTest.java @@ -15,13 +15,17 @@ ***************************************************************************/ package org.iobserve.stages.test.utility.tcp; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import kieker.common.record.IMonitoringRecord; import kieker.common.record.IRecordReceivedListener; import kieker.common.record.remotecontrol.ActivationEvent; +import kieker.common.record.remotecontrol.ActivationParameterEvent; import kieker.common.record.remotecontrol.IRemoteControlEvent; +import kieker.common.record.remotecontrol.IRemoteParameterControlEvent; import kieker.common.record.tcp.SingleSocketRecordReader; import org.iobserve.utility.tcp.RemoteControlFailedException; @@ -76,8 +80,7 @@ public static void init() { // as unit test using powermock or transform into integration test Thread.sleep(10000); } catch (final InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + TcpProbeControllerTest.LOGGER.error("Test init failed", e); } } @@ -125,6 +128,52 @@ public void testDeAndActivatePattern() throws RemoteControlFailedException { } + @Test(timeout = 30000) + public void testActivateParameterPatternAndUpdate() throws RemoteControlFailedException { + final Map state = TcpProbeControllerTest.listener.getState(); + final Map>> recordedParameters = TcpProbeControllerTest.listener + .getRecordedParameters(); + + final String testPattern = "update.pattern"; + + final String[] parameterNames = new String[] { "Pos1", "Pos2" }; + final String[][] parameters = new String[][] { + { "Pos1Parameter1", "Pos1Parameter2", "Pos1Parameter3", "Pos1Parameter4" }, + { "Pos2Parameter1", "Pos2Parameter2", "Pos2Parameter3", "Pos2Parameter4" } }; + + final Map> exampleParameter = new HashMap<>(); + exampleParameter.put(parameterNames[0], Arrays.asList(parameters[0])); + exampleParameter.put(parameterNames[1], Arrays.asList(parameters[1])); + + Assert.assertFalse(state.containsKey(testPattern)); + + TcpProbeControllerTest.tcpProbeController.activateParameterMonitoredPattern(TcpProbeControllerTest.LOCALHOST_IP, + TcpProbeControllerTest.PORT, TcpProbeControllerTest.TEST_HOST, testPattern, exampleParameter); + + Assert.assertTrue(TcpProbeControllerTest.tcpProbeController.isKnownHost(TcpProbeControllerTest.LOCALHOST_IP, + TcpProbeControllerTest.PORT)); + // wait for the other thread + while (!state.containsKey(testPattern)) { + Thread.yield(); + } + Assert.assertTrue(state.get(testPattern)); + + Assert.assertTrue(recordedParameters.get(testPattern).equals(exampleParameter)); + + final Map> exampleParameter2 = new HashMap<>(exampleParameter); + exampleParameter.put(parameterNames[1], + Arrays.asList(new String[] { "Change1", "Change2", "Change3", "Change4" })); + + TcpProbeControllerTest.tcpProbeController.updateProbeParameter(TcpProbeControllerTest.LOCALHOST_IP, + TcpProbeControllerTest.PORT, TcpProbeControllerTest.TEST_HOST, testPattern, exampleParameter2); + while (recordedParameters.get(testPattern).equals(exampleParameter)) { + Thread.yield(); + } + + Assert.assertTrue(recordedParameters.get(testPattern).equals(exampleParameter2)); + + } + /** * Terminate the thread that runs the TCP Reader. */ @@ -142,14 +191,38 @@ public static void terminate() { private static class TestListener implements IRecordReceivedListener { // NOCS private class, no // constructor private final Map state = new HashMap<>(); + private final Map>> recordedParameters = new HashMap<>(); + + @Override + public void onRecordReceived(final IMonitoringRecord arg0) { + final String pattern = ((IRemoteControlEvent) arg0).getPattern(); + + if (arg0 instanceof IRemoteParameterControlEvent) { + this.recordedParameters.put(pattern, + this.buildParameterMap(((IRemoteParameterControlEvent) arg0).getParameterNames(), + ((IRemoteParameterControlEvent) arg0).getParameters())); + } + + this.state.put(pattern, (arg0 instanceof ActivationEvent) || (arg0 instanceof ActivationParameterEvent)); + + } + + public Map>> getRecordedParameters() { + return this.recordedParameters; + } public Map getState() { return this.state; } - @Override - public void onRecordReceived(final IMonitoringRecord arg0) { - this.state.put(((IRemoteControlEvent) arg0).getPattern(), arg0 instanceof ActivationEvent); + private Map> buildParameterMap(final String[] parameterNames, + final String[][] parameterValues) { + final Map> parameterMap = new HashMap<>(); + for (int i = 0; i < parameterNames.length; i++) { + parameterMap.put(parameterNames[i], Arrays.asList(parameterValues[i])); + } + + return parameterMap; } } }