diff options
author | Jan Srnicek <jsrnicek@cisco.com> | 2017-03-14 09:29:12 +0100 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2017-03-14 14:33:40 +0100 |
commit | 5ec31f19f7a74a884e2bef8e5238fdd4cfa2c4c2 (patch) | |
tree | 53a3542d6ea26cb9d6f4ab5d827a12b2d9543db9 /vpp-management | |
parent | 4616f0300655582153362a21910bd1f0b14937ae (diff) |
HC2VPP-7 - Split vpp state/Cli RPC to separate module
Introduces VppManageModule containing
- Vpp state attributes
- CLI RPC support
- Keep-alive
Change-Id: I8907e57132cc9e57840aa3b9607fa131a77f767d
Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
Diffstat (limited to 'vpp-management')
18 files changed, 925 insertions, 0 deletions
diff --git a/vpp-management/api/asciidoc/Readme.adoc b/vpp-management/api/asciidoc/Readme.adoc new file mode 100644 index 000000000..221faa60b --- /dev/null +++ b/vpp-management/api/asciidoc/Readme.adoc @@ -0,0 +1,9 @@ += vpp-management-api + +Overview of vpp-management-api + +Provides model for two major features + +* Management attributes of underlaying vpp instance(version,pid,...) +* RPC support for invoking CLI commands + diff --git a/vpp-management/api/pom.xml b/vpp-management/api/pom.xml new file mode 100644 index 000000000..8168257e2 --- /dev/null +++ b/vpp-management/api/pom.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (c) 2017 Cisco and/or its affiliates. + ~ + ~ 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. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>io.fd.honeycomb.common</groupId> + <artifactId>api-parent</artifactId> + <version>1.17.04-SNAPSHOT</version> + </parent> + + <groupId>io.fd.hc2vpp.management</groupId> + <artifactId>vpp-management-api</artifactId> + <version>1.17.04-SNAPSHOT</version> +</project>
\ No newline at end of file diff --git a/vpp-management/api/src/main/yang/vpp-management.yang b/vpp-management/api/src/main/yang/vpp-management.yang new file mode 100644 index 000000000..2582cbea4 --- /dev/null +++ b/vpp-management/api/src/main/yang/vpp-management.yang @@ -0,0 +1,54 @@ +module vpp-management { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:vpp:management"; + prefix "vpp-m"; + + revision "2017-03-15" { + description + "This revision add support for + - Vpp state attributes read + - RPC cli support"; + } + + container vpp-state { + config false; + + description + "VPP operational data"; + + container version { + leaf name { + type string; + } + leaf build-directory { + type string; + } + leaf build-date { + type string; + } + leaf branch { + type string; + } + leaf pid { + type uint32; + description + "PID of the vpp process"; + } + description + "vlib version info"; + } + } + + rpc cli-inband { + input { + leaf cmd { + type string; + } + } + output { + leaf reply { + type string; + } + } + } +}
\ No newline at end of file diff --git a/vpp-management/asciidoc/Readme.adoc b/vpp-management/asciidoc/Readme.adoc new file mode 100644 index 000000000..8fa4da830 --- /dev/null +++ b/vpp-management/asciidoc/Readme.adoc @@ -0,0 +1,3 @@ += vpp-management-aggregator + +Overview of vpp-management-aggregator
\ No newline at end of file diff --git a/vpp-management/impl/asciidoc/Readme.adoc b/vpp-management/impl/asciidoc/Readme.adoc new file mode 100644 index 000000000..c53e5db0d --- /dev/null +++ b/vpp-management/impl/asciidoc/Readme.adoc @@ -0,0 +1,15 @@ += vpp-management-impl + +Overview of vpp-management-impl + +Provides following features + +* Read support for VPP management attributes +* Implementation of RPC support of CLI commands +* Initialization of Keep-alive service + +Exposes following configuration + +*vpp-management.json* + +* keepalive-delay - delay period for keep-alive manager
\ No newline at end of file diff --git a/vpp-management/impl/pom.xml b/vpp-management/impl/pom.xml new file mode 100644 index 000000000..da4d8ff12 --- /dev/null +++ b/vpp-management/impl/pom.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (c) 2017 Cisco and/or its affiliates. + ~ + ~ 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. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>vpp-impl-parent</artifactId> + <version>1.17.04-SNAPSHOT</version> + <relativePath>../../vpp-common/vpp-impl-parent</relativePath> + </parent> + + <modelVersion>4.0.0</modelVersion> + + <groupId>io.fd.hc2vpp.management</groupId> + <artifactId>vpp-management-impl</artifactId> + <version>1.17.04-SNAPSHOT</version> + + <dependencies> + <!-- Api --> + <dependency> + <groupId>io.fd.hc2vpp.management</groupId> + <artifactId>vpp-management-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>translate-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>rpc-api</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- DI --> + <dependency> + <groupId>com.google.inject</groupId> + <artifactId>guice</artifactId> + </dependency> + <dependency> + <groupId>com.google.inject.extensions</groupId> + <artifactId>guice-multibindings</artifactId> + </dependency> + <dependency> + <groupId>net.jmob</groupId> + <artifactId>guice.conf</artifactId> + </dependency> + + <!-- Translate --> + <dependency> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>vpp-translate-utils</artifactId> + </dependency> + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>translate-impl</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- Test --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>vpp-translate-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.inject.extensions</groupId> + <artifactId>guice-testlib</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/VppManagementConfiguration.java b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/VppManagementConfiguration.java new file mode 100644 index 000000000..53872f16e --- /dev/null +++ b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/VppManagementConfiguration.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management; + +import net.jmob.guice.conf.core.BindConfig; +import net.jmob.guice.conf.core.InjectConfig; +import net.jmob.guice.conf.core.Syntax; + +@BindConfig(value = "vpp-management", syntax = Syntax.JSON) +public class VppManagementConfiguration { + + @InjectConfig("keepalive-delay") + private int keepaliveDelay; + + public int getKeepaliveDelay() { + return this.keepaliveDelay; + } +} diff --git a/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/VppManagementModule.java b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/VppManagementModule.java new file mode 100644 index 000000000..508da64d0 --- /dev/null +++ b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/VppManagementModule.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management; + +import com.google.inject.AbstractModule; +import com.google.inject.multibindings.Multibinder; +import io.fd.hc2vpp.management.rpc.CliInbandService; +import io.fd.hc2vpp.management.state.StateReaderFactory; +import io.fd.honeycomb.rpc.RpcService; +import io.fd.honeycomb.translate.read.ReaderFactory; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import net.jmob.guice.conf.core.ConfigurationModule; + +public class VppManagementModule extends AbstractModule { + + @Override + protected void configure() { + install(ConfigurationModule.create()); + requestInjection(VppManagementConfiguration.class); + + // Readers + final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class); + readerFactoryBinder.addBinding().to(StateReaderFactory.class); + + // Executor needed for keepalives + bind(ScheduledExecutorService.class).toInstance(Executors.newScheduledThreadPool(1)); + + // RPCs + final Multibinder<RpcService> rpcsBinder = Multibinder.newSetBinder(binder(), RpcService.class); + rpcsBinder.addBinding().to(CliInbandService.class); + } +} diff --git a/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/rpc/CliInbandService.java b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/rpc/CliInbandService.java new file mode 100644 index 000000000..ab55abe3f --- /dev/null +++ b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/rpc/CliInbandService.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management.rpc; + +import com.google.inject.Inject; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.rpc.RpcService; +import io.fd.vpp.jvpp.core.dto.CliInband; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.CliInbandInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.CliInbandOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.CliInbandOutputBuilder; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +public class CliInbandService implements RpcService<CliInbandInput, CliInbandOutput>, JvppReplyConsumer { + + private final FutureJVppCore jvpp; + private static final String localName = "cli-inband"; + private static final QName name = QName.create(CliInbandInput.QNAME, localName); + private static final SchemaPath schemaPath = SchemaPath.ROOT.createChild(name); + + @Inject + public CliInbandService(@Nonnull final FutureJVppCore jvpp) { + this.jvpp = jvpp; + } + + @Override + @Nonnull + public CompletionStage<CliInbandOutput> invoke(@Nonnull final CliInbandInput input) { + final CliInband request = new CliInband(); + request.cmd = input.getCmd().getBytes(StandardCharsets.UTF_8); + request.length = request.cmd.length; + return jvpp.cliInband(request) + .thenApply( + reply -> new CliInbandOutputBuilder().setReply(new String(reply.reply)).build() + ); + } + + @Nonnull + @Override + public SchemaPath getManagedNode() { + return schemaPath; + } +} diff --git a/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/state/StateReaderFactory.java b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/state/StateReaderFactory.java new file mode 100644 index 000000000..541de30a1 --- /dev/null +++ b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/state/StateReaderFactory.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management.state; + +import com.google.inject.Inject; +import io.fd.hc2vpp.common.translate.util.ReadTimeoutException; +import io.fd.hc2vpp.common.translate.util.VppStatusListener; +import io.fd.hc2vpp.management.VppManagementConfiguration; +import io.fd.honeycomb.translate.impl.read.GenericReader; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; +import io.fd.honeycomb.translate.util.read.KeepaliveReaderWrapper; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.concurrent.ScheduledExecutorService; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.VppState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.VppStateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.vpp.state.Version; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class StateReaderFactory implements ReaderFactory { + + @Inject + private FutureJVppCore vppApi; + + @Inject + private ScheduledExecutorService keepaliveExecutor; + + @Inject + private VppStatusListener vppStatusListener; + + @Inject + private VppManagementConfiguration configuration; + + @Override + public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { + // VppState(Structural) + final InstanceIdentifier<VppState> vppStateId = InstanceIdentifier.create(VppState.class); + registry.addStructuralReader(vppStateId, VppStateBuilder.class); + // Version + // Wrap with keepalive reader to detect connection issues + // Relying on VersionCustomizer to provide a "timing out read" + registry.add(new KeepaliveReaderWrapper<>( + new GenericReader<>(vppStateId.child(Version.class), new VersionCustomizer(vppApi)), + keepaliveExecutor, ReadTimeoutException.class, configuration.getKeepaliveDelay(), vppStatusListener)); + } +} diff --git a/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/state/VersionCustomizer.java b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/state/VersionCustomizer.java new file mode 100644 index 000000000..bfbabcb0c --- /dev/null +++ b/vpp-management/impl/src/main/java/io/fd/hc2vpp/management/state/VersionCustomizer.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management.state; + +import com.google.common.primitives.UnsignedInts; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.vpp.jvpp.core.dto.ShowVersion; +import io.fd.vpp.jvpp.core.dto.ShowVersionReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import io.fd.vpp.jvpp.dto.ControlPing; +import io.fd.vpp.jvpp.dto.ControlPingReply; +import io.fd.vpp.jvpp.dto.JVppReply; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.VppStateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.vpp.state.Version; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.vpp.state.VersionBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public final class VersionCustomizer + extends FutureJVppCustomizer + implements ReaderCustomizer<Version, VersionBuilder>, ByteDataTranslator, JvppReplyConsumer { + + public VersionCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final Version readValue) { + ((VppStateBuilder) parentBuilder).setVersion(readValue); + } + + @Nonnull + @Override + public VersionBuilder getBuilder(@Nonnull InstanceIdentifier<Version> id) { + return new VersionBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Version> id, @Nonnull final VersionBuilder builder, + @Nonnull final ReadContext context) throws ReadFailedException { + + // Execute with timeout + final CompletionStage<ShowVersionReply> showVersionFuture = getFutureJVpp().showVersion(new ShowVersion()); + final ShowVersionReply reply = getReplyForRead(showVersionFuture.toCompletableFuture(), id); + + builder.setBranch(toString(reply.version)); + builder.setName(toString(reply.program)); + builder.setBuildDate(toString(reply.buildDate)); + builder.setBuildDirectory(toString(reply.buildDirectory)); + builder.setPid(getPid(id)); + } + + private Long getPid(@Nonnull final InstanceIdentifier<Version> id) throws ReadFailedException { + final CompletionStage<JVppReply<ControlPing>> request = getFutureJVpp().send(new ControlPing()); + final ControlPingReply reply = (ControlPingReply)getReplyForRead(request.toCompletableFuture(), id); + return UnsignedInts.toLong(reply.vpePid); + } + + +} diff --git a/vpp-management/impl/src/main/resources/honeycomb-minimal-resources/config/vpp-management.json b/vpp-management/impl/src/main/resources/honeycomb-minimal-resources/config/vpp-management.json new file mode 100644 index 000000000..28b25b263 --- /dev/null +++ b/vpp-management/impl/src/main/resources/honeycomb-minimal-resources/config/vpp-management.json @@ -0,0 +1,3 @@ +{ + "keepalive-delay":30 +}
\ No newline at end of file diff --git a/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/VppManagementModuleTest.java b/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/VppManagementModuleTest.java new file mode 100644 index 000000000..eb2c3a933 --- /dev/null +++ b/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/VppManagementModuleTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.HashSet; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; + +public class VppManagementModuleTest { + + @Bind + @Mock + private FutureJVppCore futureJVppCore; + + @Inject + private VppManagementConfiguration configuration; + + @Inject + private Set<ReaderFactory> readerFactories = new HashSet<>(); + + @Before + public void setUp() { + initMocks(this); + Guice.createInjector(new VppManagementModule(), BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testReaderFactories() throws Exception { + assertFalse(readerFactories.isEmpty()); + + // Test registration process (all dependencies present, topological order of readers does exist, etc.) + final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder(); + readerFactories.stream().forEach(factory -> factory.init(registryBuilder)); + assertNotNull(registryBuilder.build()); + } + + @Test + public void testConfiguration() { + assertEquals(30, configuration.getKeepaliveDelay()); + } +}
\ No newline at end of file diff --git a/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/rpc/CliInbandServiceTest.java b/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/rpc/CliInbandServiceTest.java new file mode 100644 index 000000000..dcf0a0186 --- /dev/null +++ b/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/rpc/CliInbandServiceTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management.rpc; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import io.fd.hc2vpp.common.test.util.FutureProducer; +import io.fd.vpp.jvpp.core.dto.CliInbandReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.CliInbandInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.CliInbandInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.CliInbandOutput; + +public class CliInbandServiceTest implements FutureProducer { + + @Mock + private FutureJVppCore api; + + @Test + public void testInvoke() throws Exception { + initMocks(this); + final String replyString = "CLI output"; + + final CliInbandService service = new CliInbandService(api); + final CliInbandReply reply = new CliInbandReply(); + reply.reply = replyString.getBytes(); + when(api.cliInband(any())).thenReturn(future(reply)); + + final CliInbandInput request = new CliInbandInputBuilder().setCmd("cmd").build(); + final CliInbandOutput response = service.invoke(request).toCompletableFuture().get(); + assertEquals(replyString, response.getReply()); + } +}
\ No newline at end of file diff --git a/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/state/VppStateTest.java b/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/state/VppStateTest.java new file mode 100644 index 000000000..81db88511 --- /dev/null +++ b/vpp-management/impl/src/test/java/io/fd/hc2vpp/management/state/VppStateTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * 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 io.fd.hc2vpp.management.state; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; +import io.fd.hc2vpp.common.test.util.FutureProducer; +import io.fd.honeycomb.translate.MappingContext; +import io.fd.honeycomb.translate.ModificationCache; +import io.fd.honeycomb.translate.impl.read.GenericReader; +import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.registry.ReaderRegistry; +import io.fd.vpp.jvpp.core.dto.ShowVersion; +import io.fd.vpp.jvpp.core.dto.ShowVersionReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import io.fd.vpp.jvpp.dto.ControlPing; +import io.fd.vpp.jvpp.dto.ControlPingReply; +import javax.annotation.Nonnull; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentMatchers; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.VppState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.VppStateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.vpp.state.Version; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.management.rev170315.vpp.state.VersionBuilder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class VppStateTest implements FutureProducer { + + @Mock + private FutureJVppCore api; + @Mock + private ReadContext ctx; + @Mock + private MappingContext mappingContext; + + private ReaderRegistry readerRegistry; + + /** + * Create root VppState reader with all its children wired. + */ + private static ReaderRegistry getVppStateReader(@Nonnull final FutureJVppCore jVpp) { + final CompositeReaderRegistryBuilder registry = new CompositeReaderRegistryBuilder(); + + // VppState(Structural) + final InstanceIdentifier<VppState> vppStateId = InstanceIdentifier.create(VppState.class); + registry.addStructuralReader(vppStateId, VppStateBuilder.class); + // Version + registry.add(new GenericReader<>(vppStateId.child(Version.class), new VersionCustomizer(jVpp))); + return registry.build(); + } + + @Before + public void setUp() throws Exception { + initMocks(this); + final ModificationCache cache = new ModificationCache(); + doReturn(cache).when(ctx).getModificationCache(); + doReturn(mappingContext).when(ctx).getMappingContext(); + + + readerRegistry = getVppStateReader(api); + } + + private static Version getVersion() { + return new VersionBuilder() + .setName("test") + .setBuildDirectory("1") + .setBranch("2") + .setBuildDate("3") + .setPid(0L) + .build(); + } + + private void whenShowVersionThenReturn(final Version version) { + final ShowVersionReply reply = new ShowVersionReply(); + reply.buildDate = version.getBuildDate().getBytes(); + reply.program = version.getName().getBytes(); + reply.version = version.getBranch().getBytes(); + reply.buildDirectory = version.getBuildDirectory().getBytes(); + when(api.showVersion(ArgumentMatchers.any(ShowVersion.class))).thenReturn(future(reply)); + // Version Customizer uses ControlPing to obtain PID + when(api.send(ArgumentMatchers.any(ControlPing.class))).thenReturn(future(new ControlPingReply())); + } + + @Test + public void testReadAll() throws Exception { + final Version version = getVersion(); + whenShowVersionThenReturn(version); + + final Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> dataObjects = + readerRegistry.readAll(ctx); + assertEquals(dataObjects.size(), 1); + final VppState dataObject = + (VppState) Iterables.getOnlyElement(dataObjects.get(Iterables.getOnlyElement(dataObjects.keySet()))); + assertEquals(version, dataObject.getVersion()); + } + + @Test + public void testReadSpecific() throws Exception { + final Version version = getVersion(); + whenShowVersionThenReturn(version); + + final Optional<? extends DataObject> read = readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx); + assertTrue(read.isPresent()); + assertEquals(version, ((VppState) read.get()).getVersion()); + } + + @Test + public void testReadVersion() throws Exception { + whenShowVersionThenReturn(getVersion()); + VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get(); + + Optional<? extends DataObject> read = + readerRegistry.read(InstanceIdentifier.create(VppState.class).child(Version.class), ctx); + assertTrue(read.isPresent()); + assertEquals(readRoot.getVersion(), read.get()); + } +}
\ No newline at end of file diff --git a/vpp-management/impl/src/test/resources/vpp-management.json b/vpp-management/impl/src/test/resources/vpp-management.json new file mode 100644 index 000000000..28b25b263 --- /dev/null +++ b/vpp-management/impl/src/test/resources/vpp-management.json @@ -0,0 +1,3 @@ +{ + "keepalive-delay":30 +}
\ No newline at end of file diff --git a/vpp-management/pom.xml b/vpp-management/pom.xml new file mode 100644 index 000000000..a87af1d9d --- /dev/null +++ b/vpp-management/pom.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (c) 2017 Cisco and/or its affiliates. + ~ + ~ 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. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>io.fd.honeycomb.common</groupId> + <artifactId>honeycomb-parent</artifactId> + <version>1.17.04-SNAPSHOT</version> + </parent> + + <packaging>pom</packaging> + <modelVersion>4.0.0</modelVersion> + + <groupId>io.fd.hc2vpp.management</groupId> + <artifactId>vpp-management-aggregator</artifactId> + <version>1.17.04-SNAPSHOT</version> + + <modules> + <module>api</module> + <module>impl</module> + </modules> + + <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build --> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> +</project>
\ No newline at end of file diff --git a/vpp-management/vpp_management_postman_collection.json b/vpp-management/vpp_management_postman_collection.json new file mode 100644 index 000000000..591862dd5 --- /dev/null +++ b/vpp-management/vpp_management_postman_collection.json @@ -0,0 +1,106 @@ +{ + "id": "b638a073-6954-5c89-320a-7105437dae94", + "name": "Vpp management Collection", + "description": "", + "order": [ + "1bfd69f7-e187-beb0-447c-0074aa636045" + ], + "folders": [ + { + "id": "299be85f-5ada-34f7-bd80-9fbc4e5b200a", + "name": "RPCs", + "description": "", + "order": [ + "1c552a48-498c-f2e8-8dee-2d5b67120a3a", + "2df7f806-dfb3-bf4f-9cab-0c9863ed4486", + "d4f87db0-06e5-b309-8918-d1c29f59fab1" + ], + "owner": "658985" + } + ], + "timestamp": 1489148746054, + "owner": "658985", + "public": false, + "requests": [ + { + "id": "1bfd69f7-e187-beb0-447c-0074aa636045", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", + "url": "http://localhost:8183/restconf/operational/vpp-management:vpp-state", + "preRequestScript": "", + "pathVariables": {}, + "method": "GET", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1489149850732, + "name": "Read vpp-state - oper", + "description": "", + "collectionId": "b638a073-6954-5c89-320a-7105437dae94", + "responses": [], + "rawModeData": "{\r\n \r\n \"interface\": [\r\n {\r\n \"name\": \"testInterface\",\r\n \"description\": \"for testing purposes\",\r\n \"type\": \"iana-if-type:ethernetCsmacd\",\r\n \"enabled\": \"true\",\r\n \"link-up-down-trap-enable\": \"enabled\",\r\n \"ietf-ip:ipv4\": {\r\n \"enabled\": \"true\",\r\n \"mtu\": \"1500\",\r\n \"address\": [\r\n {\r\n \"ip\": \"1.2.3.0\",\r\n \"netmask\": \"255.255.255.0\"\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n \r\n}" + }, + { + "id": "1c552a48-498c-f2e8-8dee-2d5b67120a3a", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", + "url": "http://localhost:8183/restconf/operations/vpp-management:cli-inband", + "preRequestScript": "", + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1489149921151, + "name": "show version", + "description": "The cli-inband rpc provides support for CLI commands.\nHere is equivalent of show version.", + "collectionId": "b638a073-6954-5c89-320a-7105437dae94", + "responses": [], + "rawModeData": "{\n \"input\" :\n {\n \"cmd\" : \"show version\"\n }\n}" + }, + { + "id": "2df7f806-dfb3-bf4f-9cab-0c9863ed4486", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", + "url": "http://localhost:8183/restconf/operations/vpp-management:cli-inband", + "preRequestScript": "", + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1489149929797, + "name": "show interfaces", + "description": "The cli-inband rpc provides support for CLI commands.\nHere is equivalent of show int.", + "collectionId": "b638a073-6954-5c89-320a-7105437dae94", + "responses": [], + "rawModeData": "{\n \"input\" :\n {\n \"cmd\" : \"show int\"\n }\n}" + }, + { + "id": "d4f87db0-06e5-b309-8918-d1c29f59fab1", + "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n", + "url": "http://localhost:8183/restconf/operations/vpp-management:cli-inband", + "preRequestScript": "", + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1489149940101, + "name": "create loopback interface", + "description": "The cli-inband rpc provides support for CLI commands.\nHere is equivalent of create loopback interface", + "collectionId": "b638a073-6954-5c89-320a-7105437dae94", + "responses": [], + "rawModeData": "{\n \"input\" :\n {\n \"cmd\" : \"create loopback interface\"\n }\n}" + } + ] +}
\ No newline at end of file |