diff options
Diffstat (limited to 'grpc-resource/provider/src/main/java')
5 files changed, 388 insertions, 9 deletions
diff --git a/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/GrpcClient.java b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/GrpcClient.java index c70bcec46..917882746 100644 --- a/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/GrpcClient.java +++ b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/GrpcClient.java @@ -15,15 +15,18 @@ */ package org.onap.ccsdk.sli.adaptors.grpc; -public class GrpcClient { +import java.util.Map; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; +import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus; -// ManagedChannel channel = ManagedChannelBuilder -// .forAddress("localhost", 8080) -// .executor(Executors.newSingleThreadExecutor()) -// .intercept() -// .userAgent("CCSDK gRPC Client") -// .usePlaintext() -// //.useTransportSecurity() -// .build(); +public interface GrpcClient extends SvcLogicJavaPlugin { + /** + * Send a request to process to a gRPC server. + * + * @param parameters HashMap<String,String> of parameters passed by the DG to this function. + * Required parameters are defined in implemention. + */ + QueryStatus sendRequest(Map<String, String> parameters, SvcLogicContext ctx); } diff --git a/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/GrpcProperties.java b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/GrpcProperties.java new file mode 100644 index 000000000..fef1a5963 --- /dev/null +++ b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/GrpcProperties.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2018 Bell Canada. + * + * 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.onap.ccsdk.sli.adaptors.grpc; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Optional; +import java.util.Properties; +import java.util.Set; +import org.onap.ccsdk.sli.core.utils.JREFileResolver; +import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver; +import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver; +import org.onap.ccsdk.sli.core.utils.common.BundleContextFileResolver; +import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Responsible for determining the properties file to use. + * + * <ol> + * <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li> + * <li>A directory identified by the JRE argument <code>grpc.properties</code></li> + * <li>A <code>grpc.properties</code> file located in the karaf root directory</li> + * </ol> + * + * Partial copy and adaptation of org.onap.ccsdk.sli.adaptors.aai.AAIServiceProvider + */ +public class GrpcProperties { + + private static final Logger LOG = LoggerFactory.getLogger(GrpcProperties.class); + + private static final String GRPC_PROPERTY_FILE_NAME = "grpc.properties"; + private static final String MISSING_PROPERTY_FILE = + "Missing configuration properties resource for GRPC: " + GRPC_PROPERTY_FILE_NAME; + private static final String BLUEPRINT_PROCESSOR_URL_PROP = "org.onap.ccsdk.sli.adaptors.grpc.blueprint.processor.url"; + private static final String BLUEPRINT_PROCESSOR_PORT_PROP = "org.onap.ccsdk.sli.adaptors.grpc.blueprint.processor.port"; + + private Set<PropertiesFileResolver> fileResolvers = new HashSet<>(); + private Properties properties; + + public GrpcProperties() { + fileResolvers.add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable")); + fileResolvers.add(new BundleContextFileResolver("Using property file (2) from BundleContext property", + GrpcProperties.class)); + fileResolvers.add(new JREFileResolver("Using property file (3) from JRE argument", GrpcProperties.class)); + fileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this)); + + loadProps(); + } + + public String getUrl() { + checkArgument(properties != null); + return properties.getProperty(BLUEPRINT_PROCESSOR_URL_PROP); + } + + public int getPort() { + checkArgument(properties != null); + return Integer.parseInt(properties.getProperty(BLUEPRINT_PROCESSOR_PORT_PROP)); + } + + private void checkArgument(final boolean argument) { + if (!argument) { + LOG.info("Propety file {} was missing, trying to reload it", GRPC_PROPERTY_FILE_NAME); + loadProps(); + if (properties == null) { + throw new IllegalArgumentException(MISSING_PROPERTY_FILE); + } + } + } + + private void loadProps() { + // determines properties file as according to the priority described in the class header comment + final File propertiesFile = determinePropertiesFile(); + if (propertiesFile != null) { + try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) { + properties = new Properties(); + properties.load(fileInputStream); + } catch (final IOException e) { + String errorMsg = "Failed to load properties for file: " + propertiesFile.toString(); + LOG.error(errorMsg, errorMsg); + } + } + } + + private File determinePropertiesFile() { + for (final PropertiesFileResolver resolver : fileResolvers) { + final Optional<File> fileOptional = resolver.resolveFile(GRPC_PROPERTY_FILE_NAME); + if (fileOptional.isPresent()) { + final File file = fileOptional.get(); + LOG.info("{} {}", resolver.getSuccessfulResolutionMessage(), file.getPath()); + return file; + } + } + + LOG.error(MISSING_PROPERTY_FILE); + return null; + } +} diff --git a/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/Utils.java b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/Utils.java new file mode 100644 index 000000000..831f09eaa --- /dev/null +++ b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/Utils.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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.onap.ccsdk.sli.adaptors.grpc; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +public final class Utils { + + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + private Utils() { + throw new AssertionError("Utility class"); + } + + public static String timestamp() { + LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault()); + return formatter.format(now); + } +} diff --git a/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/cds/BlueprintProcessingClient.java b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/cds/BlueprintProcessingClient.java new file mode 100644 index 000000000..33fb8fa2f --- /dev/null +++ b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/cds/BlueprintProcessingClient.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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.onap.ccsdk.sli.adaptors.grpc.cds; + +import io.grpc.ManagedChannel; +import io.grpc.internal.DnsNameResolverProvider; +import io.grpc.netty.NettyChannelBuilder; +import java.util.Map; +import org.onap.ccsdk.sli.adaptors.grpc.GrpcClient; +import org.onap.ccsdk.sli.adaptors.grpc.GrpcProperties; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BlueprintProcessingClient implements GrpcClient { + + private static final Logger log = LoggerFactory.getLogger(BlueprintProcessingClient.class); + + private ManagedChannel channel; + private BlueprintProcessingHandler handler; + + public BlueprintProcessingClient(BlueprintProcessingHandler handler, GrpcProperties props) { + this.channel = NettyChannelBuilder + .forAddress(props.getUrl(), props.getPort()) + .usePlaintext() + .nameResolverFactory(new DnsNameResolverProvider()) + .build(); + this.handler = handler; + } + + // Used by blueprint + public void start() { + log.info("BlueprintProcessingClient started"); + } + + // Used by blueprint + public void stop() { + if (channel != null) { + channel.shutdown(); + } + log.info("BlueprintProcessingClient stopped"); + } + + /* + * @param parameters HashMap<String,String> of parameters passed by the DG to this function. + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>is_force</td><td>Optional</td><td>Whether to force or not the request.</td></tr> + * <tr><td>ttl</td><td>Optional</td><td>Duration of the request.</td></tr> + * <tr><td>blueprint_name</td><td>Mandatory</td><td>Name of the blueprint to process.</td></tr> + * <tr><td>blueprint_version</td><td>Mandatory</td><td>Version of the blueprint to process.</td></tr> + * <tr><td>action</td><td>Mandatory</td><td>Action of the blueprint to process.</td></tr> + * <tr><td>mode</td><td>Mandatory</td><td>Mode to operate the transaction.</td></tr> + * </tbody> + * </table> + */ + @Override + public QueryStatus sendRequest(Map<String, String> parameters, SvcLogicContext ctx) { + return handler.process(parameters, channel); + } +}
\ No newline at end of file diff --git a/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/cds/BlueprintProcessingHandler.java b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/cds/BlueprintProcessingHandler.java new file mode 100644 index 000000000..6a618fb32 --- /dev/null +++ b/grpc-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/grpc/cds/BlueprintProcessingHandler.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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.onap.ccsdk.sli.adaptors.grpc.cds; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Struct; +import io.grpc.ManagedChannel; +import io.grpc.Status; +import io.grpc.stub.StreamObserver; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import org.onap.ccsdk.apps.controllerblueprints.common.api.ActionIdentifiers; +import org.onap.ccsdk.apps.controllerblueprints.common.api.CommonHeader; +import org.onap.ccsdk.apps.controllerblueprints.common.api.Flag; +import org.onap.ccsdk.apps.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc; +import org.onap.ccsdk.apps.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc.BluePrintProcessingServiceStub; +import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceInput; +import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceOutput; +import org.onap.ccsdk.sli.adaptors.grpc.Utils; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; +import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus; +import org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BlueprintProcessingHandler { + + private static final Logger log = LoggerFactory.getLogger(BlueprintProcessingHandler.class); + + private static final String CCSDK_ORIGINATOR = "CCSDK"; + private static final String IS_FORCE_PROP = "is_force"; + private static final String TTL_PROP = "ttl"; + private static final String BLUEPRINT_NAME_PROP = "blueprint_name"; + private static final String BLUEPRINT_VERSION_PROP = "blueprint_version"; + private static final String ACTION_PROP = "action"; + private static final String MODE_PROP = "mode"; + private static final String PAYLOAD_PROP = "payload"; + + QueryStatus process(final Map<String, String> parameters, final ManagedChannel channel) { + try { + SliPluginUtils.checkParameters(parameters, + new String[]{BLUEPRINT_NAME_PROP, BLUEPRINT_VERSION_PROP, ACTION_PROP, MODE_PROP}, log); + } catch (SvcLogicException e) { + return QueryStatus.FAILURE; + } + + final boolean isForce = Boolean.getBoolean(parameters.get(IS_FORCE_PROP)); + final int ttl = Integer.parseInt(parameters.get(TTL_PROP)); + final String blueprintName = parameters.get(BLUEPRINT_NAME_PROP); + final String blueprintVersion = parameters.get(BLUEPRINT_VERSION_PROP); + final String action = parameters.get(ACTION_PROP); + final String mode = parameters.get(MODE_PROP); + final String payload = parameters.get(PAYLOAD_PROP); + + log.info("Processing blueprint({}:{}) for action({})", blueprintVersion, blueprintName, action); + + final AtomicReference<QueryStatus> responseStatus = new AtomicReference<>(); + final CountDownLatch finishLatch = new CountDownLatch(1); + + final BluePrintProcessingServiceStub asyncStub = BluePrintProcessingServiceGrpc.newStub(channel); + + final StreamObserver<ExecutionServiceOutput> responseObserver = new StreamObserver<ExecutionServiceOutput>() { + @Override + public void onNext(ExecutionServiceOutput output) { + log.info("onNext: {}", output); + } + + @Override + public void onError(Throwable t) { + Status status = Status.fromThrowable(t); + log.error("Failed processing blueprint({}:{}) for action({}). {}", blueprintVersion, blueprintName, + action, status); + responseStatus.compareAndSet(null, QueryStatus.FAILURE); + finishLatch.countDown(); + } + + @Override + public void onCompleted() { + log.info("Completed blueprint({}:{}) for action({})", blueprintVersion, blueprintName, action); + responseStatus.compareAndSet(null, QueryStatus.SUCCESS); + finishLatch.countDown(); + } + }; + + final CommonHeader commonHeader = CommonHeader.newBuilder() + .setOriginatorId(CCSDK_ORIGINATOR) + .setRequestId(UUID.randomUUID().toString()) + .setTimestamp(Utils.timestamp()) + .setFlag(Flag.newBuilder() + .setIsForce(isForce) + .setTtl(ttl) + .build()) + .build(); + final ActionIdentifiers actionIdentifiers = ActionIdentifiers.newBuilder() + .setActionName(action) + .setBlueprintName(blueprintName) + .setBlueprintVersion(blueprintVersion) + .setMode(mode) + .build(); + + Struct struct; + try { + struct = Struct.newBuilder().mergeFrom(payload.getBytes()).build(); + } catch (InvalidProtocolBufferException e) { + log.error("Failed converting payload for blueprint({}:{}) for action({}). {}", blueprintVersion, + blueprintName, action, e); + return QueryStatus.FAILURE; + } + + final ExecutionServiceInput request = ExecutionServiceInput.newBuilder() + .setActionIdentifiers(actionIdentifiers) + .setPayload(struct) + .setCommonHeader(commonHeader).build(); + + final StreamObserver<ExecutionServiceInput> requestObserver = asyncStub.process(responseObserver); + + try { + requestObserver.onNext(request); + } catch (RuntimeException e) { + requestObserver.onError(e); + return QueryStatus.FAILURE; + } + + requestObserver.onCompleted(); + try { + finishLatch.await(1, TimeUnit.MINUTES); + } catch (InterruptedException e) { + log.error("Failed processing blueprint({}:{}) for action({}). {}", blueprintVersion, blueprintName, action, + e); + Thread.currentThread().interrupt(); + return QueryStatus.FAILURE; + } + + return responseStatus.get(); + } +}
\ No newline at end of file |