From: Giovanni Meo Date: Thu, 7 Nov 2013 16:34:55 +0000 (+0000) Subject: Merge "Added DELETE support for Bridge and Port resources" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~465 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=4f76ea30ad49331ca38ce63925b3fabf8e769731;hp=36a0cd2902fcfe51b54d3d7453b3b8c4d8d7810c Merge "Added DELETE support for Bridge and Port resources" --- diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index f7b2a01eb8..8ff25c35de 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -617,6 +617,11 @@ org.apache.catalina.filters.CorsFilter 7.0.42 + + org.opendaylight.controller.thirdparty + ganymed + 1.0-SNAPSHOT + org.opendaylight.yangtools.model diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml index 62b9ec34d0..9db5b76988 100755 --- a/opendaylight/config/pom.xml +++ b/opendaylight/config/pom.xml @@ -29,6 +29,8 @@ yang-store-impl yang-test logback-config + threadpool-config-api + threadpool-config-impl diff --git a/opendaylight/config/threadpool-config-api/pom.xml b/opendaylight/config/threadpool-config-api/pom.xml new file mode 100644 index 0000000000..b991b69213 --- /dev/null +++ b/opendaylight/config/threadpool-config-api/pom.xml @@ -0,0 +1,51 @@ + + + org.opendaylight.controller + config-subsystem + 0.2.2-SNAPSHOT + + 4.0.0 + threadpool-config-api + ${project.artifactId} + bundle + + 3.0.4 + + + + + org.opendaylight.controller + config-api + + + com.google.guava + guava + + + + + + + org.apache.felix + maven-bundle-plugin + + + + org.opendaylight.controller.config.api.*, + com.google.common.eventbus, + + + org.opendaylight.controller.config.threadpool, + org.opendaylight.controller.config.yang.threadpool + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + + \ No newline at end of file diff --git a/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ScheduledThreadPool.java b/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ScheduledThreadPool.java new file mode 100644 index 0000000000..bf6c016d35 --- /dev/null +++ b/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ScheduledThreadPool.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool; + +import java.util.concurrent.ScheduledExecutorService; + +/** + * Interface representing scheduled {@link ThreadPool}. + */ +public interface ScheduledThreadPool extends ThreadPool { + + @Override + public ScheduledExecutorService getExecutor(); +} \ No newline at end of file diff --git a/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ThreadPool.java b/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ThreadPool.java new file mode 100644 index 0000000000..701b0bcdf8 --- /dev/null +++ b/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ThreadPool.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool; + +import java.util.concurrent.ExecutorService; + +/** + * Interface representing thread pool. + */ +public interface ThreadPool { + + public ExecutorService getExecutor(); + + public int getMaxThreadCount(); +} \ No newline at end of file diff --git a/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang b/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang new file mode 100644 index 0000000000..14a20fdebc --- /dev/null +++ b/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang @@ -0,0 +1,77 @@ +// vi: set smarttab et sw=4 tabstop=4: +module threadpool { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:threadpool"; + prefix "th"; + + import config { prefix config; revision-date 2013-04-05; } + + organization "Cisco Systems, Inc."; + + contact "Robert Varga "; + + description + "This module contains the base YANG definitions for + thread-related services. + + Copyright (c)2013 Cisco Systems, Inc. All rights reserved.; + + This program and the accompanying materials are made available + under the terms of the Eclipse Public License v1.0 which + accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html"; + + revision "2013-04-09" { + description + "Added eventbus service."; + } + + revision "2013-04-05" { + description + "Updated with YANG extension for Java class specification."; + } + + revision "2013-04-03" { + description + "Initial revision by Anton Tkacik, Tomas Olvecky and + Robert Varga."; + } + + identity eventbus { + description + "Service representing an event bus. The service acts as message + router between event producers and event consumers"; + + base "config:service-type"; + config:java-class "com.google.common.eventbus.EventBus"; + } + + identity threadfactory { + description + "Service representing a ThreadFactory instance. It is directly + useful in Java world, where various library pieces need to create + threads and you may want to inject a customized thread + implementation."; + + base "config:service-type"; + config:java-class "java.util.concurrent.ThreadFactory"; + } + + identity threadpool { + description + "A simple pool of threads able to execute work."; + + base "config:service-type"; + config:java-class "org.opendaylight.controller.config.threadpool.ThreadPool"; + } + + identity scheduled-threadpool { + description + "An extension of the simple pool of threads able to schedule + work to be executed at some point in time."; + + base "threadpool"; + config:java-class "org.opendaylight.controller.config.threadpool.ScheduledThreadPool"; + } + +} diff --git a/opendaylight/config/threadpool-config-impl/pom.xml b/opendaylight/config/threadpool-config-impl/pom.xml new file mode 100644 index 0000000000..12279781a2 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/pom.xml @@ -0,0 +1,76 @@ + + + org.opendaylight.controller + config-subsystem + 0.2.2-SNAPSHOT + + 4.0.0 + threadpool-config-impl + ${project.artifactId} + bundle + + 3.0.4 + + + + + ${project.groupId} + config-api + + + ${project.groupId} + threadpool-config-api + ${project.version} + + + com.google.guava + guava + + + org.slf4j + slf4j-api + + + + + + + org.apache.felix + maven-bundle-plugin + + + + org.opendaylight.controller.config.threadpool.util, + javax.annotation.*, + org.opendaylight.controller.config.yang.threadpool.impl, + + + org.opendaylight.controller.config.api.*, + org.opendaylight.controller.config.spi.*, + org.opendaylight.controller.config.threadpool, + org.opendaylight.controller.config.yang.threadpool, + javax.management, + org.osgi.framework, + org.slf4j, + com.google.common.* + + + org.opendaylight.controller.config.threadpool.util + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.opendaylight.yangtools + yang-maven-plugin + + + + + \ No newline at end of file diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableAsyncEventBus.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableAsyncEventBus.java new file mode 100644 index 0000000000..93a08daa5d --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableAsyncEventBus.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool.util; + +import com.google.common.eventbus.AsyncEventBus; +import com.google.common.eventbus.DeadEvent; +import com.google.common.eventbus.Subscribe; + +import java.io.Closeable; +import java.io.IOException; + +import org.opendaylight.controller.config.threadpool.ThreadPool; +import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusRuntimeMXBean; +import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusRuntimeRegistration; +import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusRuntimeRegistrator; + +/** + * Closeable version of {@link AsyncEventBus}. + */ +public class CloseableAsyncEventBus extends AsyncEventBus implements Closeable { + private final ThreadPool threadPool; + private final AsyncEventBusRuntimeRegistration rootRegistration; + + public CloseableAsyncEventBus(String identifier, ThreadPool threadPool, + AsyncEventBusRuntimeRegistrator rootRegistrator) { + super(identifier, threadPool.getExecutor()); + this.threadPool = threadPool; + rootRegistration = rootRegistrator.register(new AsyncEventBusRuntimeMXBean() { + private long deadEventsCounter = 0; + + @Subscribe + public void increaseDeadEvents(DeadEvent deadEvent) { + deadEventsCounter++; + } + + @Override + public Long countDeadEvents() { + return deadEventsCounter; + } + + }); + } + + public ThreadPool getThreadPool() { + return threadPool; + } + + @Override + public void close() throws IOException { + rootRegistration.close(); + } + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableEventBus.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableEventBus.java new file mode 100644 index 0000000000..b6dd77dbf3 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableEventBus.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool.util; + +import java.io.Closeable; + +import org.opendaylight.controller.config.yang.threadpool.impl.EventBusRuntimeMXBean; +import org.opendaylight.controller.config.yang.threadpool.impl.EventBusRuntimeRegistration; +import org.opendaylight.controller.config.yang.threadpool.impl.EventBusRuntimeRegistrator; + +import com.google.common.eventbus.DeadEvent; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +/** + * Closeable {@link EventBus}. + */ +public class CloseableEventBus extends EventBus implements Closeable { + + private final EventBusRuntimeRegistration rootRegistration; + + public CloseableEventBus(String identifier, EventBusRuntimeRegistrator rootRegistrator) { + super(identifier); + rootRegistration = rootRegistrator.register(new EventBusRuntimeMXBean() { + private long deadEventsCounter = 0; + + @Subscribe + public void increaseDeadEvents(DeadEvent deadEvent) { + deadEventsCounter++; + } + + @Override + public Long countDeadEvents() { + return deadEventsCounter; + } + }); + + } + + @Override + public void close() { + rootRegistration.close(); + + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FixedThreadPoolWrapper.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FixedThreadPoolWrapper.java new file mode 100644 index 0000000000..ca034434d5 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FixedThreadPoolWrapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool.util; + +import java.io.Closeable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; + +import org.opendaylight.controller.config.threadpool.ThreadPool; + +/** + * Implementation of {@link ThreadPool} using fixed number of threads wraps + * {@link ExecutorService}. + */ +public class FixedThreadPoolWrapper implements ThreadPool, Closeable { + + private final ThreadPoolExecutor executor; + + public FixedThreadPoolWrapper(int threadCount, ThreadFactory factory) { + this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threadCount, factory); + executor.prestartAllCoreThreads(); + } + + @Override + public ExecutorService getExecutor() { + return Executors.unconfigurableExecutorService(executor); + } + + @Override + public void close() { + executor.shutdown(); + } + + @Override + public int getMaxThreadCount() { + return executor.getMaximumPoolSize(); + } + + public void setMaxThreadCount(int maxThreadCount) { + executor.setCorePoolSize(maxThreadCount); + executor.setMaximumPoolSize(maxThreadCount); + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java new file mode 100644 index 0000000000..3dfa6e2bc7 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool.util; + +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.opendaylight.controller.config.threadpool.ThreadPool; + +/** + * Implementation of {@link ThreadPool} using flexible number of threads wraps + * {@link ExecutorService}. + */ +public class FlexibleThreadPoolWrapper implements ThreadPool, Closeable { + private final ThreadPoolExecutor executor; + + public FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit, + ThreadFactory threadFactory) { + + executor = new ThreadPoolExecutor(minThreadCount, maxThreadCount, keepAlive, timeUnit, + new SynchronousQueue(), threadFactory); + executor.prestartAllCoreThreads(); + } + + @Override + public ExecutorService getExecutor() { + return Executors.unconfigurableExecutorService(executor); + } + + public int getMinThreadCount() { + return executor.getCorePoolSize(); + } + + public void setMinThreadCount(int minThreadCount) { + executor.setCorePoolSize(minThreadCount); + } + + @Override + public int getMaxThreadCount() { + return executor.getMaximumPoolSize(); + } + + public void setMaxThreadCount(int maxThreadCount) { + executor.setMaximumPoolSize(maxThreadCount); + } + + public long getKeepAliveMillis() { + return executor.getKeepAliveTime(TimeUnit.MILLISECONDS); + } + + public void setKeepAliveMillis(long keepAliveMillis) { + executor.setKeepAliveTime(keepAliveMillis, TimeUnit.MILLISECONDS); + } + + public void setThreadFactory(ThreadFactory threadFactory) { + executor.setThreadFactory(threadFactory); + } + + public void prestartAllCoreThreads() { + executor.prestartAllCoreThreads(); + } + + @Override + public void close() throws IOException { + executor.shutdown(); + } + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/NamingThreadPoolFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/NamingThreadPoolFactory.java new file mode 100644 index 0000000000..2e27d6cce8 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/NamingThreadPoolFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool.util; + +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; + +import javax.annotation.concurrent.ThreadSafe; + +import com.google.common.base.Preconditions; + +/** + * Implementation of {@link ThreadFactory}. + */ +@ThreadSafe +public class NamingThreadPoolFactory implements ThreadFactory, Closeable { + + private final ThreadGroup group; + private final String namePrefix; + private final AtomicLong threadName = new AtomicLong(); + + public NamingThreadPoolFactory(String namePrefix) { + Preconditions.checkNotNull(namePrefix); + this.group = new ThreadGroup(namePrefix); + this.namePrefix = namePrefix; + } + + @Override + public Thread newThread(Runnable r) { + return new Thread(group, r, String.format("%s-%d", group.getName(), threadName.incrementAndGet())); + } + + @Override + public void close() throws IOException { + } + + public String getNamePrefix() { + return namePrefix; + } + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/ScheduledThreadPoolWrapper.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/ScheduledThreadPoolWrapper.java new file mode 100644 index 0000000000..ee3399e1b2 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/ScheduledThreadPoolWrapper.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.threadpool.util; + +import java.io.Closeable; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; + +import org.opendaylight.controller.config.threadpool.ScheduledThreadPool; + +/** + * Implementation of {@link ScheduledThreadPool} wraps + * {@link ScheduledExecutorService}. + */ +public class ScheduledThreadPoolWrapper implements ScheduledThreadPool, Closeable { + + private final ScheduledThreadPoolExecutor executor; + private final int threadCount; + + public ScheduledThreadPoolWrapper(int threadCount, ThreadFactory factory) { + this.threadCount = threadCount; + this.executor = new ScheduledThreadPoolExecutor(threadCount, factory); + executor.prestartAllCoreThreads(); + } + + @Override + public ScheduledExecutorService getExecutor() { + return Executors.unconfigurableScheduledExecutorService(executor); + } + + @Override + public void close() { + executor.shutdown(); + } + + @Override + public int getMaxThreadCount() { + return threadCount; + } + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModule.java new file mode 100644 index 0000000000..f108303165 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModule.java @@ -0,0 +1,42 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: async-eventbus + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Tue Nov 05 15:40:46 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +import org.opendaylight.controller.config.threadpool.util.CloseableAsyncEventBus; + +/** +* +*/ +public final class AsyncEventBusModule extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractAsyncEventBusModule { + + public AsyncEventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public AsyncEventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + AsyncEventBusModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + // Add custom validation for module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new CloseableAsyncEventBus(getIdentifier().toString(), getThreadpoolDependency(), + getRootRuntimeBeanRegistratorWrapper()); + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModuleFactory.java new file mode 100644 index 0000000000..14fcf41758 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModuleFactory.java @@ -0,0 +1,18 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: async-eventbus + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Tue Nov 05 15:40:46 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +/** +* +*/ +public class AsyncEventBusModuleFactory extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractAsyncEventBusModuleFactory { + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModule.java new file mode 100644 index 0000000000..92eaee5ef2 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModule.java @@ -0,0 +1,41 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: eventbus + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Tue Nov 05 15:40:46 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +import org.opendaylight.controller.config.threadpool.util.CloseableEventBus; + +/** +* +*/ +public final class EventBusModule extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractEventBusModule { + + public EventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public EventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, EventBusModule oldModule, + java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + // Add custom validation for module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new CloseableEventBus(getIdentifier().toString(), getRootRuntimeBeanRegistratorWrapper()); + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModuleFactory.java new file mode 100644 index 0000000000..e909998a72 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModuleFactory.java @@ -0,0 +1,18 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: eventbus + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Tue Nov 05 15:40:46 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +/** +* +*/ +public class EventBusModuleFactory extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractEventBusModuleFactory { + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModule.java new file mode 100644 index 0000000000..a0a9addf03 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModule.java @@ -0,0 +1,45 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadpool-fixed + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.config.threadpool.util.FixedThreadPoolWrapper; + +/** +* +*/ +public final class FixedThreadPoolModule extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractFixedThreadPoolModule { + + public FixedThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public FixedThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + FixedThreadPoolModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + + JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute); + JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero", + maxThreadCountJmxAttribute); + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new FixedThreadPoolWrapper(getMaxThreadCount(), getThreadFactoryDependency()); + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModuleFactory.java new file mode 100644 index 0000000000..2803448fd2 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModuleFactory.java @@ -0,0 +1,18 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadpool-fixed + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +/** +* +*/ +public class FixedThreadPoolModuleFactory extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractFixedThreadPoolModuleFactory { + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModule.java new file mode 100644 index 0000000000..47b4eec689 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModule.java @@ -0,0 +1,55 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadpool-flexible + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +import java.util.concurrent.TimeUnit; + +import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.config.threadpool.util.FlexibleThreadPoolWrapper; + +/** +* +*/ +public final class FlexibleThreadPoolModule extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractFlexibleThreadPoolModule { + + public FlexibleThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public FlexibleThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + FlexibleThreadPoolModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + JmxAttributeValidationException.checkNotNull(getKeepAliveMillis(), keepAliveMillisJmxAttribute); + JmxAttributeValidationException.checkCondition(getKeepAliveMillis() > 0, "must be greater than zero", + keepAliveMillisJmxAttribute); + + JmxAttributeValidationException.checkNotNull(getMinThreadCount(), minThreadCountJmxAttribute); + JmxAttributeValidationException.checkCondition(getMinThreadCount() > 0, "must be greater than zero", + minThreadCountJmxAttribute); + + JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute); + JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero", + maxThreadCountJmxAttribute); + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new FlexibleThreadPoolWrapper(getMinThreadCount(), getMaxThreadCount(), getKeepAliveMillis(), + TimeUnit.MILLISECONDS, getThreadFactoryDependency()); + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModuleFactory.java new file mode 100644 index 0000000000..ef6ebd25e2 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModuleFactory.java @@ -0,0 +1,18 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadpool-flexible + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +/** +* +*/ +public class FlexibleThreadPoolModuleFactory extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractFlexibleThreadPoolModuleFactory { + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModule.java new file mode 100644 index 0000000000..a761727e5c --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModule.java @@ -0,0 +1,42 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadfactory-naming + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.config.threadpool.util.NamingThreadPoolFactory; + +/** +* +*/ +public final class NamingThreadFactoryModule extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractNamingThreadFactoryModule { + + public NamingThreadFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public NamingThreadFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + NamingThreadFactoryModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + JmxAttributeValidationException.checkNotNull(getNamePrefix(), namePrefixJmxAttribute); + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new NamingThreadPoolFactory(getNamePrefix()); + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModuleFactory.java new file mode 100644 index 0000000000..5e70afb93e --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModuleFactory.java @@ -0,0 +1,18 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadfactory-naming + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +/** +* +*/ +public class NamingThreadFactoryModuleFactory extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractNamingThreadFactoryModuleFactory { + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModule.java new file mode 100644 index 0000000000..42739b4b32 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModule.java @@ -0,0 +1,44 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadpool-scheduled + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.config.threadpool.util.ScheduledThreadPoolWrapper; + +/** +* +*/ +public final class ScheduledThreadPoolModule extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractScheduledThreadPoolModule { + + public ScheduledThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public ScheduledThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + ScheduledThreadPoolModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute); + JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero", + maxThreadCountJmxAttribute); + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new ScheduledThreadPoolWrapper(getMaxThreadCount(), getThreadFactoryDependency()); + } +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModuleFactory.java new file mode 100644 index 0000000000..489af822e2 --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModuleFactory.java @@ -0,0 +1,18 @@ +/** + * Generated file + + * Generated from: yang module name: threadpool-impl yang module local name: threadpool-scheduled + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Wed Nov 06 16:19:33 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.threadpool.impl; + +/** +* +*/ +public class ScheduledThreadPoolModuleFactory extends + org.opendaylight.controller.config.yang.threadpool.impl.AbstractScheduledThreadPoolModuleFactory { + +} diff --git a/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl.yang b/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl.yang new file mode 100644 index 0000000000..a2366f285a --- /dev/null +++ b/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl.yang @@ -0,0 +1,195 @@ +// vi: set smarttab et sw=4 tabstop=4: +module threadpool-impl { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl"; + prefix "th-java"; + + import threadpool { prefix th; revision-date 2013-04-09; } + import config { prefix config; revision-date 2013-04-05; } + import rpc-context { prefix rpcx; revision-date 2013-06-17; } + + organization "Cisco Systems, Inc."; + + contact "Robert Varga "; + + description + "This module contains the base YANG definitions for + thread services pure Java implementation. + + Copyright (c)2013 Cisco Systems, Inc. All rights reserved.; + + This program and the accompanying materials are made available + under the terms of the Eclipse Public License v1.0 which + accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html"; + + revision "2013-04-05" { + description + "Updated to work with new anchors."; + } + + revision "2013-04-03" { + description + "Initial revision by Anton Tkacik, Tomas Olvecky and + Robert Varga."; + } + + identity eventbus { + base config:module-type; + config:provided-service th:eventbus; + config:java-name-prefix EventBus; + } + + augment "/config:modules/config:module/config:configuration" { + case eventbus { + when "/config:modules/config:module/config:type = 'eventbus'"; + // No real configuration + } + } + + augment "/config:modules/config:module/config:state" { + case eventbus { + when "/config:modules/config:module/config:type = 'eventbus'"; + rpcx:rpc-context-instance "event-bus-rpc"; + } + } + + identity event-bus-rpc; + + identity async-eventbus { + base config:module-type; + config:provided-service th:eventbus; + config:java-name-prefix AsyncEventBus; + } + + augment "/config:modules/config:module/config:configuration" { + case async-eventbus { + when "/config:modules/config:module/config:type = 'async-eventbus'"; + container threadpool { + uses config:service-ref { + refine type { + //mandatory true; + config:required-identity th:threadpool; + } + } + } + } + } + + augment "/config:modules/config:module/config:state" { + case async-eventbus { + when "/config:modules/config:module/config:type = 'async-eventbus'"; + rpcx:rpc-context-instance "event-bus-rpc"; + } + } + + rpc get-dead-events-count { + config:java-name-prefix countDeadEvents; + input { + uses rpcx:rpc-context-ref { + refine context-instance { + rpcx:rpc-context-instance event-bus-rpc; + } + } + } + output { + leaf result { + type uint32; + } + } + } + + identity threadfactory-naming { + base config:module-type; + config:provided-service th:threadfactory; + config:java-name-prefix NamingThreadFactory; + } + + augment "/config:modules/config:module/config:configuration" { + case threadfactory-naming { + when "/config:modules/config:module/config:type = 'threadfactory-naming'"; + leaf name-prefix { + type string; + } + } + } + + identity threadpool-fixed { + base config:module-type; + config:provided-service th:threadpool; + config:java-name-prefix FixedThreadPool; + } + + augment "/config:modules/config:module/config:configuration" { + case threadpool-fixed { + when "/config:modules/config:module/config:type = 'threadpool-fixed'"; + leaf max-thread-count { + type uint16; + } + + container threadFactory { + uses config:service-ref { + refine type { + //mandatory true; + config:required-identity th:threadfactory; + } + } + } + } + } + + identity threadpool-flexible { + base config:module-type; + config:provided-service th:threadpool; + config:java-name-prefix FlexibleThreadPool; + } + + augment "/config:modules/config:module/config:configuration" { + case threadpool-flexible { + when "/config:modules/config:module/config:type = 'threadpool-flexible'"; + leaf max-thread-count { + type uint16; + } + leaf minThreadCount { + type uint16; + } + leaf keepAliveMillis { + type uint32; + } + + container threadFactory { + uses config:service-ref { + refine type { + // mandatory true; + config:required-identity th:threadfactory; + } + } + } + } + } + + identity threadpool-scheduled { + base config:module-type; + config:provided-service th:scheduled-threadpool; + config:java-name-prefix ScheduledThreadPool; + } + + augment "/config:modules/config:module/config:configuration" { + case threadpool-scheduled { + when "/config:modules/config:module/config:type = 'threadpool-scheduled'"; + leaf max-thread-count { + type uint16; + } + + container threadFactory { + uses config:service-ref { + refine type { + // mandatory true; + config:required-identity th:threadfactory; + } + } + } + } + } +} + diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 4482df0780..a0d7162b3f 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -81,7 +81,7 @@ org.opendaylight.controller - sal-compability + sal-compatibility ${mdsal.version} @@ -287,7 +287,7 @@ 2.4 - + org.opendaylight.yangtools.thirdparty antlr4-runtime-osgi-nohead 4.0 @@ -334,11 +334,15 @@ yang-model-api - - org.opendaylight.yangtools.model - yang-ext - + + org.opendaylight.yangtools.model + yang-ext + + + org.opendaylight.controller.thirdparty + ganymed + diff --git a/opendaylight/md-sal/flow-management-compatibility/pom.xml b/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml similarity index 94% rename from opendaylight/md-sal/flow-management-compatibility/pom.xml rename to opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml index 5c24baa650..3c8bf97961 100644 --- a/opendaylight/md-sal/flow-management-compatibility/pom.xml +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml @@ -2,8 +2,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.opendaylight.controller - sal-parent + org.opendaylight.controller + compatibility-parent 1.0-SNAPSHOT flow-management-compatibility @@ -81,7 +81,7 @@ org.opendaylight.controller - sal-compability + sal-compatibility 1.0-SNAPSHOT diff --git a/opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend similarity index 98% rename from opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend rename to opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend index 58248590a1..d462251a9f 100644 --- a/opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend @@ -15,7 +15,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager import static com.google.common.base.Preconditions.*; import static extension org.opendaylight.controller.md.frm.compatibility.FlowConfigMapping.*; -import static extension org.opendaylight.controller.sal.compability.NodeMapping.*; +import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*; import org.opendaylight.controller.sal.common.util.Arguments import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem import org.opendaylight.yangtools.yang.common.RpcResult diff --git a/opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend similarity index 89% rename from opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend rename to opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend index c567dc0097..e4d9173378 100644 --- a/opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend @@ -3,9 +3,9 @@ package org.opendaylight.controller.md.frm.compatibility import org.opendaylight.controller.forwardingrulesmanager.FlowConfig import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder -import static extension org.opendaylight.controller.sal.compability.NodeMapping.* -import static org.opendaylight.controller.sal.compability.MDFlowMapping.* -import static org.opendaylight.controller.sal.compability.ToSalConversionsUtils.* +import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* +import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.* +import static org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.* import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow diff --git a/opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java similarity index 100% rename from opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java rename to opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java new file mode 100644 index 0000000000..a82eedc3f9 --- /dev/null +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java @@ -0,0 +1,38 @@ +package org.opendaylight.controller.md.frm.compatibility; + +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; +import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class SampleConsumer { + + ConsumerContext context; + + void addFlowExample() { + + DataBrokerService dataService = context.getSALService(DataBrokerService.class); + + DataModificationTransaction transaction = dataService.beginTransaction(); + Flow flow = createSampleFlow("foo", null); + InstanceIdentifier path = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, flow.getKey()) + .toInstance(); + transaction.putConfigurationData(path, flow); + + transaction.commit(); + + dataService.readConfigurationData(path); + } + + Flow createSampleFlow(String name, NodeRef node) { + FlowBuilder ret = new FlowBuilder(); + FlowKey key = new FlowKey(name, node); + ret.setKey(key); + return ret.build(); + } +} diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml new file mode 100644 index 0000000000..d9fb18f84d --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml @@ -0,0 +1,109 @@ + + 4.0.0 + + org.opendaylight.controller + compatibility-parent + 1.0-SNAPSHOT + + inventory-topology-compatibility + bundle + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + + + + + org.apache.felix + maven-bundle-plugin + true + + + Forwarding Rules Manager Adapter + for MD-SAL + + + + + org.eclipse.xtend + xtend-maven-plugin + + + maven-clean-plugin + + + + + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + switchmanager + 0.6.1-SNAPSHOT + + + org.opendaylight.controller + topologymanager + 0.4.1-SNAPSHOT + + + org.slf4j + slf4j-api + + + com.google.guava + guava + + + junit + junit + test + + + org.mockito + mockito-all + test + + + org.eclipse.xtend + org.eclipse.xtend.lib + + + org.opendaylight.controller.model + model-flow-management + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-util + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-topology + 1.0-SNAPSHOT + + + org.opendaylight.controller + forwardingrulesmanager + 0.4.1-SNAPSHOT + + + org.opendaylight.controller + sal-compatibility + 1.0-SNAPSHOT + + + diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.xtend new file mode 100644 index 0000000000..262e8486ee --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.xtend @@ -0,0 +1,83 @@ +package org.opendaylight.controller.md.compatibility.inventory + +import org.opendaylight.controller.switchmanager.ISwitchManager +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.DataObject +import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider +import java.util.ArrayList +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector +import static extension org.opendaylight.controller.sal.compatibility.InventoryMapping.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder + +class InventoryReader implements RuntimeDataProvider { + + @Property + var ISwitchManager switchManager; + + override readConfigurationData(InstanceIdentifier path) { + + // Topology and Inventory are operational only + return null; + } + + override readOperationalData(InstanceIdentifier path) { + val type = path.targetType; + var DataObject data = null; + switch (type) { + case Nodes: + data = readNodes(path as InstanceIdentifier) + case Node: + data = readNode(path as InstanceIdentifier) + case NodeConnector: + data = readNodeConnector(path as InstanceIdentifier) + } + return data; + } + + def DataObject readNodeConnector(InstanceIdentifier identifier) { + val nodeConnector = identifier.toAdNodeConnector(); + return constructNodeConnector(nodeConnector) + } + + def DataObject readNode(InstanceIdentifier identifier) { + val node = identifier.toAdNode(); + return constructNode(node); + } + + + def Node constructNode(org.opendaylight.controller.sal.core.Node node) { + val connectors = switchManager.getNodeConnectors(node) + + val tpList = new ArrayList(connectors.size) + for (connector : connectors) { + tpList.add(constructNodeConnector(connector)); + } + + val it = new NodeBuilder() + key = node.toNodeKey(); + nodeConnector = tpList + return build(); + } + + def NodeConnector constructNodeConnector(org.opendaylight.controller.sal.core.NodeConnector connector) { + val it = new NodeConnectorBuilder() + key = connector.toNodeConnectorKey() + return build(); + } + + def readNodes(InstanceIdentifier identifier) { + val nodes = switchManager.nodes + val nodeList = new ArrayList(nodes.size) + for (node : nodes) { + nodeList.add(constructNode(node)) + } + val it = new NodesBuilder(); + node = nodeList + return build() + + } +} diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.xtend new file mode 100644 index 0000000000..430b5957ef --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.xtend @@ -0,0 +1,289 @@ +package org.opendaylight.controller.md.compatibility.switchmanager + +import org.opendaylight.controller.switchmanager.ISwitchManager +import org.opendaylight.controller.sal.core.NodeConnector +import org.opendaylight.controller.sal.core.Property +import java.util.List +import org.opendaylight.controller.sal.core.Node +import java.net.InetAddress +import org.opendaylight.controller.sal.binding.api.data.DataBrokerService +import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* +import org.opendaylight.controller.sal.core.Description +import org.opendaylight.controller.sal.core.Tier +import org.opendaylight.controller.sal.core.Bandwidth +import org.opendaylight.controller.sal.core.ForwardingMode +import org.opendaylight.controller.sal.core.MacAddress + +import org.slf4j.LoggerFactory +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.DataObject +import java.net.NetworkInterface +import java.net.SocketException +import java.util.Collections +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes +import java.util.ArrayList +import org.opendaylight.controller.switchmanager.Switch +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId +import java.util.Map +import java.util.HashSet +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortState + +class CompatibleSwitchManager extends ConfigurableSwitchManager implements ISwitchManager { + + private static val log = LoggerFactory.getLogger(CompatibleSwitchManager) + + @org.eclipse.xtend.lib.Property + var DataBrokerService dataService; + + override addNodeConnectorProp(NodeConnector nodeConnector, Property prop) { + val it = dataService.beginTransaction + val path = nodeConnector.toNodeConnectorRef + + // TODO: Update FlowCapableNode + return null; + } + + override createProperty(String propName, String propValue) { + try { + if (propName.equalsIgnoreCase(Description.propertyName)) { + return new Description(propValue); + } else if (propName.equalsIgnoreCase(Tier.TierPropName)) { + val tier = Integer.parseInt(propValue); + return new Tier(tier); + } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) { + val bw = Long.parseLong(propValue); + return new Bandwidth(bw); + } else if (propName.equalsIgnoreCase(ForwardingMode.name)) { + val mode = Integer.parseInt(propValue); + return new ForwardingMode(mode); + } else if (propName.equalsIgnoreCase(MacAddress.name)) { + return new MacAddress(propValue); + } else { + log.debug("Not able to create {} property", propName); + } + } catch (Exception e) { + log.debug("createProperty caught exception {}", e.getMessage()); + } + return null; + } + + override doesNodeConnectorExist(NodeConnector nc) { + val ref = nc.toNodeConnectorRef + return dataService.readOperationalData(ref.value as InstanceIdentifier) !== null + } + + override getControllerMAC() { + var byte[] macAddress = null; + + try { + val nis = NetworkInterface.getNetworkInterfaces(); + while (nis.hasMoreElements()) { + val ni = nis.nextElement(); + try { + macAddress = ni.getHardwareAddress(); + return macAddress; + } catch (SocketException e) { + log.error("Failed to acquire controller MAC: ", e); + } + } + } catch (SocketException e) { + log.error("Failed to acquire controller MAC: ", e); + return macAddress; + } + + if (macAddress == null) { + log.warn("Failed to acquire controller MAC: No physical interface found"); + + // This happens when running controller on windows VM, for example + // Try parsing the OS command output + } + return macAddress; + } + + override getControllerProperties() { + return Collections.emptyMap() + } + + override getControllerProperty(String propertyName) { + return null; + } + + override getNetworkDevices() { + val path = InstanceIdentifier.builder().node(Nodes).toInstance; + val data = dataService.readOperationalData(path) as Nodes; + val ret = new ArrayList(); + for (node : data.node) { + ret.add(node.toSwitch()); + } + return ret; + } + + override getNodeConnector(Node node, String nodeConnectorName) { + val key = new NodeConnectorKey(new NodeConnectorId(nodeConnectorName)); + return new NodeConnector(MD_SAL_TYPE, key, node); + } + + override getNodeConnectorProp(NodeConnector nodeConnector, String propName) { + getNodeConnectorProps(nodeConnector).get(propName); + } + + override getNodeConnectorProps(NodeConnector nodeConnector) { + val ref = nodeConnector.toNodeConnectorRef + val data = readNodeConnector(ref.value); + return data.toAdProperties(); + } + + override getNodeConnectors(Node node) { + val ref = node.toNodeRef; + val data = readNode(ref.value); + val ret = new HashSet(); + for (nc : data.nodeConnector) { + + val adConnector = new NodeConnector(MD_SAL_TYPE, nc.key, node); + ret.add(adConnector); + } + return ret; + } + + override getNodeDescription(Node node) { + (getNodeProps(node).get(Description.propertyName) as Description).value; + } + + override getNodeMAC(Node node) { + (getNodeProps(node).get(MacAddress.name) as MacAddress).macAddress; + } + + override getNodeProp(Node node, String propName) { + getNodeProps(node).get(propName) + } + + override getNodeProps(Node node) { + val ref = node.toNodeRef; + val data = dataService.readOperationalData(ref.value as InstanceIdentifier) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; + return data.toAdProperties(); + } + + override getNodes() { + val path = InstanceIdentifier.builder().node(Nodes).toInstance; + val data = dataService.readOperationalData(path) as Nodes; + val ret = new HashSet(); + for (node : data.node) { + ret.add(new Node(MD_SAL_TYPE, node.key)); + } + return ret; + } + + def Switch toSwitch(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node) { + val adNode = new Node(MD_SAL_TYPE, node.key); + val sw = new Switch(adNode) + return sw; + } + + override getPhysicalNodeConnectors(Node node) { + val ref = node.toNodeRef; + val data = readNode(ref.value); + val ret = new HashSet(); + for (nc : data.nodeConnector) { + val flowConnector = nc.getAugmentation(FlowCapableNodeConnector) + val adConnector = new NodeConnector(MD_SAL_TYPE, nc.key, node); + ret.add(adConnector); + } + return ret; + } + + def Map toAdProperties( + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector connector) { + return Collections.emptyMap + } + + def Map toAdProperties( + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node connector) { + return Collections.emptyMap + } + + def readNode(InstanceIdentifier ref) { + dataService.readOperationalData(ref as InstanceIdentifier) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node + } + + def readNodeConnector(InstanceIdentifier ref) { + dataService.readOperationalData(ref as InstanceIdentifier) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector + } + + override getSpanPorts(Node node) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override getSubnetByNetworkAddress(InetAddress networkAddress) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override getUpNodeConnectors(Node node) { + val ref = node.toNodeRef + val data = readNode(ref.value); + val ret = new HashSet(); + for (nc : data.nodeConnector) { + val flowConn = nc.getAugmentation(FlowCapableNodeConnector); + if (flowConn != null && flowConn.state == PortState.Live) { + ret.add(new NodeConnector(MD_SAL_TYPE, nc.key, node)); + } + } + return ret; + } + + override isNodeConnectorEnabled(NodeConnector nodeConnector) { + val ref = nodeConnector.toNodeConnectorRef + val data = readNodeConnector(ref.value); + + return true; + } + + override isSpecial(NodeConnector p) { + val ref = p.toNodeConnectorRef + val data = readNodeConnector(ref.value); + + return true; + } + + override removeControllerProperty(String propertyName) { + // NOOP + } + + override removeNodeAllProps(Node node) { + // NOOP: not supported node has more properties than AD-SAL is capable to see + } + + override removeNodeConnectorAllProps(NodeConnector nodeConnector) { + // NOOP: not supported node has more properties than AD-SAL is capable to see + } + + override removeNodeConnectorProp(NodeConnector nc, String propName) { + // NOOP: not supported node has more properties than AD-SAL is capable to see + } + + override removeNodeProp(Node node, String propName) { + // NOOP: not supported node has more properties than AD-SAL is capable to see + } + + override removePortsFromSubnet(String name, List nodeConnectors) { + // NOOP + } + + override removeSubnet(String name) { + // NOOP + } + + override setControllerProperty(Property property) { + // NOOP + } + + override setNodeProp(Node node, Property prop) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addPortsToSubnet(String name, List nodeConnectors) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + } diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.xtend new file mode 100644 index 0000000000..122aa32f12 --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.xtend @@ -0,0 +1,71 @@ +package org.opendaylight.controller.md.compatibility.switchmanager + +import org.opendaylight.controller.switchmanager.ISwitchManager +import org.opendaylight.controller.switchmanager.SpanConfig +import org.opendaylight.controller.switchmanager.SwitchConfig +import org.opendaylight.controller.switchmanager.SubnetConfig + +/** + * + * THis methods should be backed by config subsystem. + * + */ +abstract class ConfigurableSwitchManager implements ISwitchManager { + + override saveSwitchConfig() { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override removeSpanConfig(SpanConfig cfgObject) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addSubnet(SubnetConfig configObject) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + final override addSpanConfig(SpanConfig configObject) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + final override getSpanConfigList() { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + final override updateSwitchConfig(SwitchConfig cfgObject) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + final override updateNodeConfig(SwitchConfig switchConfig) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + final override getSubnetConfig(String subnet) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + final override removeNodeConfig(String nodeId) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + final override removeSubnet(SubnetConfig configObject) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + final override getSubnetsConfigList() { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + final override getSwitchConfig(String nodeId) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override modifySubnet(SubnetConfig configObject) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } +} diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.xtend new file mode 100644 index 0000000000..5a4aae36a8 --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.xtend @@ -0,0 +1,67 @@ +package org.opendaylight.controller.md.compatibility.topology + +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.DataObject +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology +import org.opendaylight.controller.sal.core.Edge +import java.util.Set +import org.opendaylight.controller.sal.core.Property +import org.opendaylight.controller.sal.core.NodeConnector + +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeKey +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.LinkKey +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.LinkId +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node +import org.opendaylight.controller.sal.compatibility.InventoryMapping +class TopologyMapping { + + new(TopologyKey path, InstanceIdentifier key) { + // NOOP + } + + def Edge toAdTopologyEdge(InstanceIdentifier identifier) { + val linkKey = (identifier.path.last as IdentifiableItem).key; + val components = linkKey.linkId.value.split("::::"); + val tail = InventoryMapping.nodeConnectorFromId(components.get(0)); + val head = InventoryMapping.nodeConnectorFromId(components.get(1)); + return new Edge(tail, head); + } + + def NodeConnector toAdTopologyNodeConnector(InstanceIdentifier identifier) { + val tpKey = (identifier.path.last as IdentifiableItem).key; + return InventoryMapping.nodeConnectorFromId(tpKey.tpId.value); + } + + def org.opendaylight.controller.sal.core.Node toAdTopologyNode( + InstanceIdentifier identifier) { + val tpKey = (identifier.path.last as IdentifiableItem).key; + return InventoryMapping.nodeFromNodeId(tpKey.nodeId.value); + } + + + + def NodeKey toTopologyNodeKey(org.opendaylight.controller.sal.core.Node node) { + val nodeId = new NodeId(InventoryMapping.toNodeId(node)); + return new NodeKey(nodeId); + } + + def TerminationPointKey toTopologyTerminationPointKey(NodeConnector nc) { + val node = nc.node; + val nodeId = new TpId(InventoryMapping.toNodeConnectorId(nc)) + return new TerminationPointKey(nodeId); + } + + def LinkKey toTopologyLinkKey(Edge edge) { + val sourceTp = edge.tailNodeConnector.toTopologyTerminationPointKey; + val destTp = edge.headNodeConnector.toTopologyTerminationPointKey; + val linkId = new LinkId('''«sourceTp.tpId»::::«destTp.tpId»''') + return new LinkKey(linkId); + } +} diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.xtend new file mode 100644 index 0000000000..fb9d2b8786 --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.xtend @@ -0,0 +1,151 @@ +package org.opendaylight.controller.md.compatibility.topology + +import org.opendaylight.controller.switchmanager.ISwitchManager +import org.opendaylight.controller.topologymanager.ITopologyManager +import org.opendaylight.controller.md.sal.common.api.data.DataReader +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.DataObject +import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology +import org.opendaylight.controller.md.compatibility.topology.TopologyMapping +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.LinkBuilder + +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyBuilder +import java.util.ArrayList +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeBuilder +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeKey +import org.opendaylight.controller.sal.core.NodeConnector +import org.opendaylight.controller.sal.topology.TopoEdgeUpdate +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TopologyId +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointBuilder +import org.opendaylight.controller.sal.core.Edge +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.SourceBuilder +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.DestinationBuilder + +class TopologyReader implements RuntimeDataProvider { + + @Property + var ISwitchManager switchManager; + + @Property + var ITopologyManager topologyManager; + + @Property + val TopologyKey topologyKey; + + @Property + val InstanceIdentifier topologyPath; + + @Property + val extension TopologyMapping mapping; + + new() { + _topologyKey = new TopologyKey(new TopologyId("compatibility:ad-sal")); + _topologyPath = InstanceIdentifier.builder().node(NetworkTopology).child(Topology, topologyKey).toInstance; + _mapping = new TopologyMapping(topologyKey, topologyPath); + } + + override readConfigurationData(InstanceIdentifier path) { + + // Topology and Inventory are operational only + return null; + } + + override readOperationalData(InstanceIdentifier path) { + val type = path.targetType; + var DataObject data = null; + if (false == topologyPath.contains(path)) { + return null; + } + switch (type) { + case Topology: + data = readTopology(path as InstanceIdentifier) + case Node: + data = readNode(path as InstanceIdentifier) + case TerminationPoint: + data = readTerminationPoint(path as InstanceIdentifier) + case Link: + data = readLink(path as InstanceIdentifier) + } + return data; + } + + def DataObject readLink(InstanceIdentifier identifier) { + val edge = identifier.toAdTopologyEdge(); + val properties = topologyManager?.edges?.get(edge); + + return constructLink(edge); + } + + def DataObject readTerminationPoint(InstanceIdentifier identifier) { + val nodeConnector = identifier.toAdTopologyNodeConnector(); + return constructTerminationPoint(nodeConnector) + } + + def DataObject readNode(InstanceIdentifier identifier) { + val node = identifier.toAdTopologyNode(); + return constructNode(node); + } + + def DataObject readTopology(InstanceIdentifier identifier) { + + //val nodeConnectors = switchManager. + val nodes = switchManager.nodes + val edges = topologyManager.edges + + val nodeList = new ArrayList(nodes.size) + for (node : nodes) { + nodeList.add(constructNode(node)) + } + + val linkList = new ArrayList(edges.size) + for (edge : edges.keySet) { + linkList.add(constructLink(edge)) + } + + val it = new TopologyBuilder(); + key = topologyKey + node = nodeList + link = linkList + return build() + } + + def constructLink(Edge edge) { + val sourceNc = edge.tailNodeConnector + val destNc = edge.headNodeConnector + + val it = new LinkBuilder() + key = edge.toTopologyLinkKey(); + source = new SourceBuilder().setSourceNode(sourceNc.node.toTopologyNodeKey.nodeId).setSourceTp( + sourceNc.toTopologyTerminationPointKey.tpId).build() + destination = new DestinationBuilder().setDestNode(destNc.node.toTopologyNodeKey.nodeId).setDestTp( + destNc.toTopologyTerminationPointKey.tpId).build + return build() + } + + def Node constructNode(org.opendaylight.controller.sal.core.Node node) { + val connectors = switchManager.getNodeConnectors(node) + + val tpList = new ArrayList(connectors.size) + for (connector : connectors) { + tpList.add(constructTerminationPoint(connector)); + } + + val it = new NodeBuilder() + key = node.toTopologyNodeKey(); + terminationPoint = tpList + return build(); + } + + def TerminationPoint constructTerminationPoint(NodeConnector connector) { + val it = new TerminationPointBuilder() + key = connector.toTopologyTerminationPointKey + return build(); + } + +} diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.xtend new file mode 100644 index 0000000000..ad7537bc0d --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.xtend @@ -0,0 +1,94 @@ +package org.opendaylight.controller.md.compatibility.topologymanager + +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint +import org.opendaylight.controller.sal.core.NodeConnector +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology +import java.util.Map +import org.opendaylight.controller.sal.core.Edge +import java.util.Set +import java.util.List +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node +import java.util.Collections +import com.google.common.collect.FluentIterable +import java.util.HashSet +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId +import org.opendaylight.controller.sal.compatibility.NodeMapping +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.Source +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.Destination +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey +import java.util.HashMap + +class AdSalTopologyMapping { + + val TopologyKey topologyMapping; + @Property + val InstanceIdentifier topologyPath; + + new(TopologyKey topology) { + topologyMapping = topology; + _topologyPath = InstanceIdentifier.builder.node(NetworkTopology).child(Topology, topology).toInstance; + } + + def InstanceIdentifier toTerminationPoint(NodeConnector connector) { + InstanceIdentifier.builder(topologyPath).node(Node).child(TerminationPoint, connector.toTerminationPointKey()).toInstance; + } + + def Map> toEdgePropertiesMap(Iterable links) { + val ret = new HashMap> + for (link : links) { + ret.put(link.toEdge(), link.toProperties()) + } + return ret; + } + + def Set toEdges(Iterable links) { + val ret = new HashSet + for (link : links) { + ret.add(link.toEdge) + } + return ret; + } + + def Edge toEdge(Link link) { + val tail = link.source.toNodeConnector(); + val head = link.destination.toNodeConnector(); + return new Edge(tail, head); + } + + def org.opendaylight.controller.sal.core.Node toAdNode(Node node) { + return node.nodeId.toAdNode; + } + + def org.opendaylight.controller.sal.core.Node toAdNode( + org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId node) { + val key = new NodeKey(new NodeId(node)) + return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, key); + } + + def NodeConnector toNodeConnector(Source ref) { + val adNode = ref.sourceNode.toAdNode(); + val key = new NodeConnectorKey(new NodeConnectorId(ref.sourceTp)) + return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode); + } + + def NodeConnector toNodeConnector(Destination ref) { + val adNode = ref.destNode.toAdNode(); + val key = new NodeConnectorKey(new NodeConnectorId(ref.destTp)) + return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode); + } + + def TerminationPointKey toTerminationPointKey(NodeConnector connector) { + } + + def Set toProperties(Link link) { + } +} diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.xtend new file mode 100644 index 0000000000..c6a4912f2d --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.xtend @@ -0,0 +1,85 @@ +package org.opendaylight.controller.md.compatibility.topologymanager + +import org.opendaylight.controller.topologymanager.ITopologyManager +import org.opendaylight.controller.sal.core.NodeConnector +import org.opendaylight.controller.sal.core.Host +import org.opendaylight.controller.sal.core.UpdateType +import java.util.Set +import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader +import java.util.HashMap +import org.opendaylight.controller.sal.core.Edge +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint +import com.google.common.collect.FluentIterable + +class CompatibleTopologyManager extends ConfigurableLinkManager implements ITopologyManager { + + @Property + var TypeSafeDataReader dataReader; + + @Property + var extension AdSalTopologyMapping topologyMapping; + + override getEdges() { + val topology = dataReader.readOperationalData(topologyPath); + return topology.link.toEdgePropertiesMap(); + } + + override getNodeEdges() { + val topology = dataReader.readOperationalData(topologyPath); + val ret = new HashMap>; + for (node : topology.node) { + val adNode = node.toAdNode(); + val adEdges = FluentIterable.from(topology.link).filter[ + source.sourceNode == node.nodeId || destination.destNode == node.nodeId].toEdges(); + ret.put(adNode, adEdges) + } + return ret; + } + + /** + * Returns true if point is connected to link + */ + def isInternal(TerminationPoint point) { + val topology = dataReader.readConfigurationData(topologyPath); + val tpId = point.key.tpId; + return FluentIterable.from(topology.link).anyMatch( + [ + source.sourceTp == tpId || destination.destTp == tpId + ]) + } + + override getNodeConnectorWithHost() { + } + + override getHostAttachedToNodeConnector(NodeConnector p) { + val tpPath = p.toTerminationPoint(); + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override getHostsAttachedToNodeConnector(NodeConnector p) { + val topology = dataReader.readOperationalData(topologyPath); + + throw new UnsupportedOperationException("Hosts not mapped yet") + } + + override getNodesWithNodeConnectorHost() { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + override isInternal(NodeConnector p) { + val tpPath = p.toTerminationPoint(); + val connector = dataReader.readConfigurationData(tpPath); + return connector.isInternal(); + } + + override updateHostLink(NodeConnector p, Host h, UpdateType t, + Set props) { + // Update app defined topology + } + + override saveConfig() { + // FIXME: commit configuration + } + +} diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.xtend new file mode 100644 index 0000000000..da3bf66424 --- /dev/null +++ b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.xtend @@ -0,0 +1,24 @@ +package org.opendaylight.controller.md.compatibility.topologymanager + +import org.opendaylight.controller.topologymanager.ITopologyManager +import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig + +abstract class ConfigurableLinkManager implements ITopologyManager { + + final override addUserLink(TopologyUserLinkConfig link) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + + final override deleteUserLink(String linkName) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + + final override getUserLinks() { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/compatibility/pom.xml b/opendaylight/md-sal/compatibility/pom.xml new file mode 100644 index 0000000000..a829380e68 --- /dev/null +++ b/opendaylight/md-sal/compatibility/pom.xml @@ -0,0 +1,101 @@ + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + + compatibility-parent + pom + MD-SAL to AD-SAL Adaptation + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + + + sal-compatibility + inventory-topology-compatibility + flow-management-compatibility + + + + + org.opendaylight.controller + sal + 0.5.1-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + com.google.guava + guava + + + org.eclipse.xtend + org.eclipse.xtend.lib + + + junit + junit + test + + + + + + + org.eclipse.xtend + xtend-maven-plugin + + + org.apache.felix + maven-bundle-plugin + + + ${project.name} + org.opendaylight.controller.sal.compability.ComponentActivator + + + + + org.jacoco + jacoco-maven-plugin + + org.opendaylight.controller.* + + + + pre-test + + prepare-agent + + + + post-test + test + + report + + + + + + + + diff --git a/opendaylight/md-sal/sal-compability/pom.xml b/opendaylight/md-sal/compatibility/sal-compatibility/pom.xml similarity index 65% rename from opendaylight/md-sal/sal-compability/pom.xml rename to opendaylight/md-sal/compatibility/sal-compatibility/pom.xml index 6d992de015..15a9a689b3 100644 --- a/opendaylight/md-sal/sal-compability/pom.xml +++ b/opendaylight/md-sal/compatibility/sal-compatibility/pom.xml @@ -3,10 +3,10 @@ 4.0.0 org.opendaylight.controller - sal-parent + compatibility-parent 1.0-SNAPSHOT - sal-compability + sal-compatibility MD-SAL to AD-SAL Adaptation scm:git:ssh://git.opendaylight.org:29418/controller.git @@ -15,44 +15,11 @@ - - org.opendaylight.controller - sal - 0.5.1-SNAPSHOT - - - org.opendaylight.controller.model - model-flow-service - 1.0-SNAPSHOT - org.opendaylight.controller.model model-flow-statistics 1.0-SNAPSHOT - - org.opendaylight.controller - sal-common-util - 1.0-SNAPSHOT - - - org.opendaylight.controller - sal-binding-api - 1.0-SNAPSHOT - - - com.google.guava - guava - - - org.eclipse.xtend - org.eclipse.xtend.lib - - - junit - junit - test - bundle @@ -68,7 +35,7 @@ ${project.name} - org.opendaylight.controller.sal.compability.ComponentActivator + org.opendaylight.controller.sal.compatibility.ComponentActivator diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ComponentActivator.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend similarity index 97% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ComponentActivator.xtend rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend index 5c1723ec7e..b460edff74 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ComponentActivator.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend @@ -1,10 +1,10 @@ -package org.opendaylight.controller.sal.compability +package org.opendaylight.controller.sal.compatibility import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey import org.opendaylight.controller.sal.core.Node import org.opendaylight.controller.sal.core.NodeConnector -import static org.opendaylight.controller.sal.compability.NodeMapping.* +import static org.opendaylight.controller.sal.compatibility.NodeMapping.* import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey import org.apache.felix.dm.Component import java.util.Arrays diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/DataPacketAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend similarity index 93% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/DataPacketAdapter.xtend rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend index 422599c62b..ce6af6469e 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/DataPacketAdapter.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability +package org.opendaylight.controller.sal.compatibility import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FlowProgrammerAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend similarity index 93% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FlowProgrammerAdapter.xtend rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend index 385007b375..da652e65a7 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FlowProgrammerAdapter.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability +package org.opendaylight.controller.sal.compatibility import java.util.concurrent.ExecutionException import org.opendaylight.controller.sal.core.Node @@ -15,10 +15,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalF import org.opendaylight.yangtools.yang.common.RpcResult import org.slf4j.LoggerFactory -import static org.opendaylight.controller.sal.compability.MDFlowMapping.* +import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.* -import static extension org.opendaylight.controller.sal.compability.NodeMapping.* -import static extension org.opendaylight.controller.sal.compability.ToSalConversionsUtils.* +import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* +import static extension org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.* class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener { diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FromSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java similarity index 98% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FromSalConversionsUtils.java rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java index 8b8668999e..a31d8e265d 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FromSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability; +package org.opendaylight.controller.sal.compatibility; import static org.opendaylight.controller.sal.match.MatchType.DL_DST; import static org.opendaylight.controller.sal.match.MatchType.DL_SRC; @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.opendaylight.controller.sal.compatibility.MDFlowMapping; import org.opendaylight.controller.sal.core.NodeConnector; @@ -25,7 +26,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; - import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.Address; @@ -57,18 +57,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; - import com.google.common.net.InetAddresses; - - - - - - - - -import static org.opendaylight.controller.sal.compability.ProtocolConstants.*; -import static org.opendaylight.controller.sal.compability.NodeMapping.*; +import static org.opendaylight.controller.sal.compatibility.NodeMapping.*; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.*; public class FromSalConversionsUtils { diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/InventoryAndReadAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend similarity index 98% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/InventoryAndReadAdapter.xtend rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend index c9c60e2141..8ac6f1b050 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/InventoryAndReadAdapter.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability +package org.opendaylight.controller.sal.compatibility import org.opendaylight.controller.sal.reader.IPluginInReadService import org.opendaylight.controller.sal.core.NodeConnector @@ -8,8 +8,8 @@ import org.opendaylight.controller.sal.core.NodeTable import org.opendaylight.controller.sal.binding.api.data.DataBrokerService import static extension org.opendaylight.controller.sal.common.util.Arguments.* -import static extension org.opendaylight.controller.sal.compability.NodeMapping.* -import static org.opendaylight.controller.sal.compability.MDFlowMapping.* +import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* +import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.* import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend new file mode 100644 index 0000000000..0ea991830b --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.compatibility + +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef + +class InventoryMapping { + + static def org.opendaylight.controller.sal.core.NodeConnector toAdNodeConnector( + InstanceIdentifier identifier) { + val tpKey = (identifier.path.last as IdentifiableItem).key; + return nodeConnectorFromId(tpKey.id.value); + } + + static def org.opendaylight.controller.sal.core.Node toAdNode(InstanceIdentifier identifier) { + val tpKey = (identifier.path.last as IdentifiableItem).key; + return nodeFromNodeId(tpKey.id.value); + } + + + static def NodeRef toNodeRef(org.opendaylight.controller.sal.core.Node node) { + val nodeId = new NodeKey(new NodeId(node.toNodeId)) + val path = InstanceIdentifier.builder().node(Nodes).child(Node,nodeId).toInstance; + return new NodeRef(path); + } + + static def NodeKey toNodeKey(org.opendaylight.controller.sal.core.Node node) { + val nodeId = new NodeId(node.toNodeId) + return new NodeKey(nodeId); + } + + static def NodeConnectorKey toNodeConnectorKey(org.opendaylight.controller.sal.core.NodeConnector nc) { + val nodeId = new NodeConnectorId(nc.toNodeConnectorId) + return new NodeConnectorKey(nodeId); + } + + static def String toNodeId(org.opendaylight.controller.sal.core.Node node) { + '''ad-sal:«node.type»::«node.nodeIDString»''' + } + + static def String toNodeConnectorId(org.opendaylight.controller.sal.core.NodeConnector nc) { + '''«nc.node.toNodeId»::«nc.nodeConnectorIDString»''' + } + + static def org.opendaylight.controller.sal.core.Node nodeFromNodeId(String nodeId) { + return nodeFromString(nodeId.split("::")) + } + + static def nodeConnectorFromId(String invId) { + return nodeConnectorFromString(invId.split("::")); + } + + private static def org.opendaylight.controller.sal.core.NodeConnector nodeConnectorFromString(String[] string) { + val node = nodeFromString(string.subList(0, 1)); + return org.opendaylight.controller.sal.core.NodeConnector.fromStringNoNode(string.get(2), node); + } + + private static def org.opendaylight.controller.sal.core.Node nodeFromString(String[] strings) { + val type = strings.get(0).substring(6); + org.opendaylight.controller.sal.core.Node.fromString(type, strings.get(1)) + } + +} diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/MDFlowMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend similarity index 98% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/MDFlowMapping.xtend rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend index cd03df8398..b43e8af661 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/MDFlowMapping.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability; +package org.opendaylight.controller.sal.compatibility; import com.google.common.net.InetAddresses import java.math.BigInteger @@ -73,8 +73,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherTyp import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp -import static extension org.opendaylight.controller.sal.compability.FromSalConversionsUtils.* -import static extension org.opendaylight.controller.sal.compability.NodeMapping.* +import static extension org.opendaylight.controller.sal.compatibility.FromSalConversionsUtils.* +import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/NodeMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend similarity index 98% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/NodeMapping.xtend rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend index 2a771def12..b180d86c32 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/NodeMapping.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability +package org.opendaylight.controller.sal.compatibility import org.opendaylight.controller.sal.core.Node import org.opendaylight.controller.sal.core.NodeConnector diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ProtocolConstants.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ProtocolConstants.java similarity index 88% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ProtocolConstants.java rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ProtocolConstants.java index 1828dac464..7392f5c763 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ProtocolConstants.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ProtocolConstants.java @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability; +package org.opendaylight.controller.sal.compatibility; public class ProtocolConstants { // source: http://en.wikipedia.org/wiki/Ethertype diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java similarity index 98% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalConversionsUtils.java rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java index 41b425ef2d..5009e5dfb7 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java @@ -1,6 +1,7 @@ -package org.opendaylight.controller.sal.compability; +package org.opendaylight.controller.sal.compatibility; import com.google.common.net.InetAddresses; + import org.opendaylight.controller.sal.action.Controller; import org.opendaylight.controller.sal.action.Drop; import org.opendaylight.controller.sal.action.Flood; @@ -91,10 +92,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.ETHERNET_ARP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.SCTP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.TCP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.UDP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.SCTP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP; import static org.opendaylight.controller.sal.match.MatchType.DL_DST; import static org.opendaylight.controller.sal.match.MatchType.DL_SRC; import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE; diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/DataPacketServiceAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/DataPacketServiceAdapter.java similarity index 92% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/DataPacketServiceAdapter.java rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/DataPacketServiceAdapter.java index 8efa17340d..aa67600124 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/DataPacketServiceAdapter.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/DataPacketServiceAdapter.java @@ -1,6 +1,6 @@ -package org.opendaylight.controller.sal.compability.adsal; +package org.opendaylight.controller.sal.compatibility.adsal; -import org.opendaylight.controller.sal.compability.NodeMapping; +import org.opendaylight.controller.sal.compatibility.NodeMapping; import org.opendaylight.controller.sal.packet.IPluginInDataPacketService; import org.opendaylight.controller.sal.packet.RawPacket; import org.opendaylight.controller.sal.packet.RawPacket; diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java new file mode 100644 index 0000000000..ae427455a4 --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java @@ -0,0 +1,84 @@ +package org.opendaylight.controller.sal.compatibility.adsal; + +import java.util.concurrent.Future; + +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.common.util.Futures; +import org.opendaylight.controller.sal.common.util.Rpcs; +import org.opendaylight.controller.sal.compatibility.InventoryMapping; +import org.opendaylight.controller.sal.compatibility.NodeMapping; +import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener; +import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService; +import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListener { + + private static final Logger LOG = LoggerFactory.getLogger(FlowServiceAdapter.class); + + private IFlowProgrammerService delegate; + + private NotificationProviderService publish; + + @Override + public void flowRemoved(org.opendaylight.controller.sal.core.Node node, Flow flow) { + FlowRemovedBuilder flowRemovedBuilder = new FlowRemovedBuilder(); + flowRemovedBuilder.setNode(InventoryMapping.toNodeRef(node)); + publish.publish(flowRemovedBuilder.build()); + } + + @Override + public void flowErrorReported(org.opendaylight.controller.sal.core.Node node, long rid, Object err) { + // TODO Auto-generated method stub + + } + + @Override + public Future> addFlow(AddFlowInput input) { + + Flow flow = ToSalConversionsUtils.toFlow(input); + @SuppressWarnings("unchecked") + org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier) input + .getNode().getValue()); + Status status = delegate.addFlowAsync(node, flow); + Void rpcResultType = null; + return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); + } + + @Override + public Future> removeFlow(RemoveFlowInput input) { + + Flow flow = ToSalConversionsUtils.toFlow(input); + @SuppressWarnings("unchecked") + org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier) input + .getNode().getValue()); + Status status = delegate.removeFlowAsync(node, flow); + Void rpcResultType = null; + return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); + + } + + @Override + public Future> updateFlow(UpdateFlowInput input) { + @SuppressWarnings("unchecked") + org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier) input + .getNode().getValue()); + Flow originalFlow = ToSalConversionsUtils.toFlow(input.getOriginalFlow()); + Flow updatedFlow = ToSalConversionsUtils.toFlow(input.getUpdatedFlow()); + Status status = delegate.modifyFlowAsync(node, originalFlow, updatedFlow); + Void rpcResultType = null; + return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); + } +} diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowStatisticsAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java similarity index 98% rename from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowStatisticsAdapter.java rename to opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java index 3963aacd03..f5c5620d7c 100644 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowStatisticsAdapter.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java @@ -1,4 +1,4 @@ -package org.opendaylight.controller.sal.compability.adsal; +package org.opendaylight.controller.sal.compatibility.adsal; import java.math.BigInteger; import java.util.ArrayList; @@ -8,8 +8,8 @@ import java.util.concurrent.Future; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; import org.opendaylight.controller.sal.common.util.Futures; import org.opendaylight.controller.sal.common.util.Rpcs; -import org.opendaylight.controller.sal.compability.NodeMapping; -import org.opendaylight.controller.sal.compability.ToSalConversionsUtils; +import org.opendaylight.controller.sal.compatibility.NodeMapping; +import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils; import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.flowprogrammer.Flow; diff --git a/opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestFromSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java similarity index 85% rename from opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestFromSalConversionsUtils.java rename to opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java index e6d05553ef..c37cce0837 100644 --- a/opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestFromSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java @@ -1,60 +1,32 @@ -package org.opendaylight.controller.sal.compability; +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. +* +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v1.0 which accompanies this distribution, +* and is available at http://www.eclipse.org/legal/epl-v10.html +*/ +package org.opendaylight.controller.sal.compatibility.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.ETHERNET_ARP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.SCTP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.TCP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.UDP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.SCTP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP; import java.util.ArrayList; import java.util.List; import org.junit.Test; -import org.opendaylight.controller.sal.action.Action; -import org.opendaylight.controller.sal.action.Flood; -import org.opendaylight.controller.sal.action.FloodAll; -import org.opendaylight.controller.sal.action.HwPath; -import org.opendaylight.controller.sal.action.Loopback; -import org.opendaylight.controller.sal.action.PopVlan; -import org.opendaylight.controller.sal.action.PushVlan; -import org.opendaylight.controller.sal.action.SetDlDst; -import org.opendaylight.controller.sal.action.SetDlSrc; -import org.opendaylight.controller.sal.action.SetDlType; -import org.opendaylight.controller.sal.action.SetNextHop; -import org.opendaylight.controller.sal.action.SetNwDst; -import org.opendaylight.controller.sal.action.SetNwSrc; -import org.opendaylight.controller.sal.action.SetNwTos; -import org.opendaylight.controller.sal.action.SetTpDst; -import org.opendaylight.controller.sal.action.SetTpSrc; -import org.opendaylight.controller.sal.action.SetVlanCfi; -import org.opendaylight.controller.sal.action.SetVlanId; -import org.opendaylight.controller.sal.action.SetVlanPcp; -import org.opendaylight.controller.sal.action.SwPath; +import org.opendaylight.controller.sal.action.*; +import org.opendaylight.controller.sal.compatibility.MDFlowMapping; +import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodAllAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.HwPathAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.LoopbackAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PopVlanAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushVlanAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlDstAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlSrcAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlTypeAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNextHopAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwDstAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwSrcAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwTosAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpDstAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpSrcAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanCfiAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanIdAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanPcpAction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SwPathAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.Address; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.address.Ipv4; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match; diff --git a/opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestToSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java similarity index 82% rename from opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestToSalConversionsUtils.java rename to opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java index 615eca0a67..e251dd02a0 100644 --- a/opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestToSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java @@ -1,77 +1,43 @@ -package org.opendaylight.controller.sal.compability; +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.compatibility.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigInteger; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -import com.google.common.net.InetAddresses; import org.junit.Test; -import org.opendaylight.controller.sal.action.Flood; -import org.opendaylight.controller.sal.action.FloodAll; -import org.opendaylight.controller.sal.action.HwPath; -import org.opendaylight.controller.sal.action.Loopback; -import org.opendaylight.controller.sal.action.Output; -import org.opendaylight.controller.sal.action.PopVlan; -import org.opendaylight.controller.sal.action.PushVlan; -import org.opendaylight.controller.sal.action.SetDlDst; -import org.opendaylight.controller.sal.action.SetDlSrc; -import org.opendaylight.controller.sal.action.SetDlType; -import org.opendaylight.controller.sal.action.SetNextHop; -import org.opendaylight.controller.sal.action.SetNwDst; -import org.opendaylight.controller.sal.action.SetNwSrc; -import org.opendaylight.controller.sal.action.SetNwTos; -import org.opendaylight.controller.sal.action.SetTpDst; -import org.opendaylight.controller.sal.action.SetTpSrc; -import org.opendaylight.controller.sal.action.SetVlanCfi; -import org.opendaylight.controller.sal.action.SetVlanId; -import org.opendaylight.controller.sal.action.SetVlanPcp; -import org.opendaylight.controller.sal.action.SwPath; +import org.opendaylight.controller.sal.action.*; +import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.MatchType; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.VlanCfi; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.ControllerActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.DropActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodAllActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.HwPathActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.LoopbackActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.OutputActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PopMplsActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PopVlanActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushMplsActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushPbbActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushVlanActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlDstActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlSrcActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlTypeActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetMplsTtlActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNextHopActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwDstActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwSrcActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwTosActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwTtlActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetQueueActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpDstActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpSrcActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanCfiActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanIdActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanPcpActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SwPathActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.Action; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.ActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.Address; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.address.Ipv4Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.address.Ipv6Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType; @@ -79,20 +45,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder; @@ -100,21 +54,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder; -import java.math.BigInteger; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import com.google.common.net.InetAddresses; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.ETHERNET_ARP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.SCTP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.TCP; -import static org.opendaylight.controller.sal.compability.ProtocolConstants.UDP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.SCTP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP; +import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP; public class TestToSalConversionsUtils { // prefix: diff --git a/opendaylight/md-sal/model/model-topology/pom.xml b/opendaylight/md-sal/model/model-topology/pom.xml new file mode 100644 index 0000000000..c91b9dd53a --- /dev/null +++ b/opendaylight/md-sal/model/model-topology/pom.xml @@ -0,0 +1,31 @@ + + + + model-parent + org.opendaylight.controller.model + 1.0-SNAPSHOT + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + + 4.0.0 + model-topology + bundle + + + + org.opendaylight.controller.model + model-inventory + 1.0-SNAPSHOT + + + org.opendaylight.yangtools.model + ietf-topology + 2013.07.12.2-SNAPSHOT + + + diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang new file mode 100644 index 0000000000..33c03ba059 --- /dev/null +++ b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang @@ -0,0 +1,34 @@ +module opendaylight-topology-inventory { + yang-version 1; + namespace "urn:opendaylight:model:topology:inventory"; + // replace with IANA namespace when assigned + prefix "nt"; + + import yang-ext { prefix "ext"; } + import ietf-inet-types { prefix "inet"; } + import opendaylight-inventory {prefix "inv";} + import opendaylight-topology {prefix "odt";} + import network-topology {prefix "topo";} + + organization "TBD"; + + contact "WILL-BE-DEFINED-LATER"; + + revision 2013-10-30 { + description + "Initial revision."; + } + + augment "/topo:network-topology/topo:topology/topo:node" { + ext:augment-identifier "inventory-node"; + uses inv:node-context-ref; + } + + augment "/topo:network-topology/topo:topology/topo:node/topo:termination-point" { + ext:augment-identifier "inventory-node-connector"; + leaf node-connector { + ext:context-reference "inv:node-connector-context"; + type inv:node-connector-ref; + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang new file mode 100644 index 0000000000..038a1b7c67 --- /dev/null +++ b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang @@ -0,0 +1,64 @@ +module opendaylight-topology { + yang-version 1; + namespace "urn:opendaylight:model:topology:general"; + // replace with IANA namespace when assigned + prefix "nt"; + + import yang-ext { prefix "ext"; } + import ietf-inet-types { prefix "inet"; } + import opendaylight-inventory {prefix "inv";} + import network-topology {prefix "topo";} + + organization "TBD"; + + contact "WILL-BE-DEFINED-LATER"; + + revision 2013-10-30 { + description + "Initial revision."; + } + + identity node-type { + + } + + typedef node-type-ref { + type identityref { + base node-type; + } + } + + identity topology-context { + + } + + identity topology-node-context { + + } + + grouping node-identifiers { + list node-identifier { + key "type identifier"; + leaf type { + type node-type-ref; + } + leaf identifier { + type inet:uri; + } + } + } + + augment "/topo:network-topology/topo:topology" { + ext:context-instance "topology-context"; + } + + /* Inventory Augmentations */ + augment "/topo:network-topology/topo:topology/topo:node" { + ext:context-instance "topology-node-context"; + } + + augment "/topo:network-topology/topo:topology/topo:node" { + ext:augment-identifier "identifiable-node"; + uses node-identifiers; + } +} diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang new file mode 100644 index 0000000000..2fecb327ca --- /dev/null +++ b/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang @@ -0,0 +1,48 @@ +module opendaylight-topology-view { + yang-version 1; + namespace "urn:opendaylight:model:topology:view"; + // replace with IANA namespace when assigned + prefix "nt"; + + import yang-ext { prefix "ext"; } + import ietf-inet-types { prefix "inet"; } + import network-topology {prefix "topo";} + import opendaylight-topology {prefix "odl";} + + organization "TBD"; + + contact "WILL-BE-DEFINED-LATER"; + + revision 2013-10-30 { + description + "Initial revision."; + } + + + grouping aggregate-topology { + leaf-list original-topology { + type topo:topology-ref; + } + } + + grouping aggregate-node { + list original-node { + leaf topology { + type topo:topology-ref; + } + leaf node { + type topo:node-ref; + } + } + } + + augment "/topo:network-topology/topo:topology" { + ext:augment-identifier "aggregated-topology"; + uses aggregate-topology; + } + + augment "/topo:network-topology/topo:topology/topo:node" { + ext:augment-identifier "aggregated-node"; + uses aggregate-node; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/model/pom.xml b/opendaylight/md-sal/model/pom.xml index ca97232cfb..eccb691fa7 100644 --- a/opendaylight/md-sal/model/pom.xml +++ b/opendaylight/md-sal/model/pom.xml @@ -28,6 +28,7 @@ model-flow-service model-flow-statistics model-flow-management + model-topology diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 06df83ec7f..fd89da4dd0 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -28,23 +28,26 @@ sal-binding-config sal-binding-broker + sal-binding-util + samples model - - sal-compability sal-connector-api sal-rest-connector - flow-management-compatibility clustered-data-store/implementation + inventory-manager + + compatibility + sal-zeromq-connector test diff --git a/opendaylight/md-sal/sal-binding-api/pom.xml b/opendaylight/md-sal/sal-binding-api/pom.xml index c1dccdf532..cfbd4f7b71 100644 --- a/opendaylight/md-sal/sal-binding-api/pom.xml +++ b/opendaylight/md-sal/sal-binding-api/pom.xml @@ -38,6 +38,7 @@ org.osgi org.osgi.core ${osgi.core.version} + provided diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml index b8b37af58e..9ca025b393 100644 --- a/opendaylight/md-sal/sal-binding-broker/pom.xml +++ b/opendaylight/md-sal/sal-binding-broker/pom.xml @@ -77,12 +77,14 @@ ${project.groupId}.${project.artifactId} + + org.opendaylight.controller.sal.binding.spi.*, + org.opendaylight.controller.config.yang.md.sal.binding.impl, - org.opendaylight.controller.sal.binding.spi, - org.opendaylight.controller.sal.binding.spi.*, org.opendaylight.controller.sal.binding.impl, org.opendaylight.controller.sal.binding.impl.*, + org.opendaylight.controller.sal.binding.codegen, org.opendaylight.controller.sal.binding.codegen.*, diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend index 9356ecda88..6ed63b21dd 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend @@ -5,23 +5,13 @@ import org.opendaylight.controller.sal.binding.api.data.DataChangeListener import org.opendaylight.controller.sal.binding.api.data.DataProviderService import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener import org.opendaylight.controller.md.sal.common.api.TransactionStatus -import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification import org.opendaylight.controller.md.sal.common.api.data.DataReader import org.opendaylight.yangtools.concepts.AbstractObjectRegistration import org.opendaylight.yangtools.concepts.ListenerRegistration -import static extension org.opendaylight.controller.sal.binding.impl.util.MapUtils.*; -import java.util.Collection -import java.util.Map.Entry -import java.util.HashSet -import java.util.Set import com.google.common.collect.Multimap import static com.google.common.base.Preconditions.*; import java.util.List -import java.util.LinkedList -import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider import com.google.common.collect.HashMultimap import java.util.concurrent.ExecutorService import java.util.concurrent.Callable @@ -30,15 +20,17 @@ import org.opendaylight.controller.sal.common.util.Rpcs import java.util.Collections import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction import java.util.ArrayList -import org.opendaylight.controller.sal.common.util.RpcErrors +import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter +import org.opendaylight.yangtools.concepts.CompositeObjectRegistration +import java.util.Arrays class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService { @Property var ExecutorService executor; - Multimap configReaders = HashMultimap.create(); - Multimap operationalReaders = HashMultimap.create(); + val dataReadRouter = new BindingAwareDataReaderRouter; + Multimap listeners = HashMultimap.create(); Multimap commitHandlers = HashMultimap.create(); @@ -47,13 +39,11 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer } override readConfigurationData(InstanceIdentifier path) { - val readers = configReaders.getAllChildren(path); - return readers.readConfiguration(path); + return dataReadRouter.readConfigurationData(path); } override readOperationalData(InstanceIdentifier path) { - val readers = operationalReaders.getAllChildren(path); - return readers.readOperational(path); + return dataReadRouter.readOperationalData(path); } override registerCommitHandler(InstanceIdentifier path, @@ -69,20 +59,12 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer return reg; } - override registerDataReader(InstanceIdentifier path, - DataReader, DataObject> provider) { - val ret = new DataReaderRegistration(provider, this); - ret.paths.add(path); - configReaders.put(path, ret); - operationalReaders.put(path, ret); - return ret; - } - - protected def removeReader(DataReaderRegistration reader) { - for (path : reader.paths) { - operationalReaders.remove(path, reader); - configReaders.remove(path, reader); - } + override registerDataReader(InstanceIdentifier path,DataReader,DataObject> reader) { + + val confReg = dataReadRouter.registerConfigurationReader(path,reader); + val dataReg = dataReadRouter.registerOperationalReader(path,reader); + + return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg)); } protected def removeListener(DataChangeListenerRegistration registration) { @@ -92,39 +74,8 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer protected def removeCommitHandler(DataCommitHandlerRegistration registration) { commitHandlers.remove(registration.path, registration); } - - protected def DataObject readConfiguration( - Collection> entries, - InstanceIdentifier path) { - - val List partialResults = new LinkedList(); - for (entry : entries) { - partialResults.add(entry.value.instance.readConfigurationData(path)) - } - return merge(path, partialResults); - } - - protected def DataObject readOperational( - Collection> entries, - InstanceIdentifier path) { - - val List partialResults = new LinkedList(); - for (entry : entries) { - partialResults.add(entry.value.instance.readOperationalData(path)) - } - return merge(path, partialResults); - } - - protected def DataObject merge(InstanceIdentifier identifier, List objects) { - - // FIXME: implement real merge - if (objects.size > 0) { - return objects.get(0); - } - } protected def getActiveCommitHandlers() { - return commitHandlers.entries.map[ value.instance].toSet } @@ -137,26 +88,6 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer } -package class DataReaderRegistration extends // -AbstractObjectRegistration, DataObject>> { - - DataBrokerImpl dataBroker; - - @Property - val Set> paths; - - new(DataReader, DataObject> instance, DataBrokerImpl broker) { - super(instance) - dataBroker = broker; - _paths = new HashSet(); - } - - override protected removeRegistration() { - dataBroker.removeReader(this); - } - -} - package class DataChangeListenerRegistration extends AbstractObjectRegistration implements ListenerRegistration { DataBrokerImpl dataBroker; diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend deleted file mode 100644 index 398a2196c6..0000000000 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.sal.binding.impl - -import org.opendaylight.controller.sal.common.DataStoreIdentifier -import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider - -class DataProviderContext { - - @Property - var DataStoreIdentifier identifier; - @Property - var RuntimeDataProvider provider; -} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java index 9cb9caf7c1..c970fc5e92 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java @@ -22,6 +22,7 @@ public class DataTransactionImpl extends AbstractDataModification, DataObject> { + + override protected merge(InstanceIdentifier path, Iterable data) { + return data.iterator.next; + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-binding-util/pom.xml b/opendaylight/md-sal/sal-binding-util/pom.xml new file mode 100644 index 0000000000..26041ea85e --- /dev/null +++ b/opendaylight/md-sal/sal-binding-util/pom.xml @@ -0,0 +1,33 @@ + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + + sal-binding-util + bundle + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + + + + com.google.guava + guava + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + org.apache.felix + org.apache.felix.dependencymanager + 3.1.0 + + + diff --git a/opendaylight/md-sal/sal-binding-util/src/main/java/org/opendaylight/controller/md/sal/binding/util/TypeSafeDataReader.java b/opendaylight/md-sal/sal-binding-util/src/main/java/org/opendaylight/controller/md/sal/binding/util/TypeSafeDataReader.java new file mode 100644 index 0000000000..738a14a9bd --- /dev/null +++ b/opendaylight/md-sal/sal-binding-util/src/main/java/org/opendaylight/controller/md/sal/binding/util/TypeSafeDataReader.java @@ -0,0 +1,38 @@ +package org.opendaylight.controller.md.sal.binding.util; + +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public final class TypeSafeDataReader { + + + private final DataReader,DataObject> delegate; + + + + public DataReader, DataObject> getDelegate() { + return delegate; + } + + + public TypeSafeDataReader(DataReader, DataObject> delegate) { + this.delegate = delegate; + } + + + @SuppressWarnings("unchecked") + public D readConfigurationData(InstanceIdentifier path) { + return (D) delegate.readConfigurationData(path); + } + + + @SuppressWarnings("unchecked") + public D readOperationalData(InstanceIdentifier path) { + return (D) delegate.readOperationalData(path); + } + + public static TypeSafeDataReader forReader(DataReader, DataObject> delegate) { + return new TypeSafeDataReader(delegate); + } +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java index 0fea50b777..30a607d95b 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java @@ -13,19 +13,75 @@ import java.util.Set; // FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments. // import org.opendaylight.yangtools.concepts.Path; +public interface DataChange

*/, D> { -public interface DataChange

*/,D> { + /** + * Returns a map of paths and newly created objects + * + * @return map of paths and newly created objects + */ + Map getCreatedOperationalData(); - Map getCreatedOperationalData(); + /** + * Returns a map of paths and newly created objects + * + * @return map of paths and newly created objects + */ + Map getCreatedConfigurationData(); - Map getUpdatedOperationalData(); + /** + * Returns a map of paths and respective updated objects after update. + * + * Original state of the object is in + * {@link #getOriginalOperationalData()} + * + * @return map of paths and newly created objects + */ + Map getUpdatedOperationalData(); - Set

getRemovedOperationalData(); + /** + * Returns a map of paths and respective updated objects after update. + * + * Original state of the object is in + * {@link #getOriginalConfigurationData()} + * + * @return map of paths and newly created objects + */ + Map getUpdatedConfigurationData(); - Map getCreatedConfigurationData(); - Map getUpdatedConfigurationData(); + /** + * Returns a set of paths of removed objects. + * + * Original state of the object is in + * {@link #getOriginalConfigurationData()} + * + * @return map of paths and newly created objects + */ Set

getRemovedConfigurationData(); + /** + * Returns a set of paths of removed objects. + * + * Original state of the object is in + * {@link #getOriginalOperationalData()} + * + * @return map of paths and newly created objects + */ + Set

getRemovedOperationalData(); + + /** + * Return a map of paths and original state of updated and removed objectd. + * + * @return map of paths and original state of updated and removed objectd. + */ + Map getOriginalConfigurationData(); + + /** + * Return a map of paths and original state of updated and removed objectd. + * + * @return map of paths and original state of updated and removed objectd. + */ + Map getOriginalOperationalData(); } diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java index 5905413745..144a81b256 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java @@ -11,4 +11,17 @@ import org.opendaylight.yangtools.concepts.Immutable; public interface DataChangeEvent extends DataChange, Immutable { + /** + * Returns a new subtree of data, which starts at the path + * where listener was registered. + * + */ + D getUpdatedConfigurationSubtree(); + + /** + * Returns a new subtree of data, which starts at the path + * where listener was registered. + * + */ + D getUpdatedOperationalSubtree(); } diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java index 85e3d8f57c..90de13d15e 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java @@ -84,7 +84,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult; */ public interface DataCommitHandler

*/,D> { - + DataCommitTransaction requestCommit(DataModification modification); public interface DataCommitTransaction

*/,D> { diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModification.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModification.java index 1ab7c34589..d059766dea 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModification.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModification.java @@ -16,7 +16,7 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus; // import org.opendaylight.yangtools.concepts.Path; import org.opendaylight.yangtools.yang.common.RpcResult; -public interface DataModification

*/, D> extends DataReader { +public interface DataModification

*/, D> extends DataChange, DataReader { /** * Returns transaction identifier @@ -27,21 +27,29 @@ public interface DataModification

*/, D> extends DataReader< TransactionStatus getStatus(); + /** + * + * Use {@link #putOperationalData(Object, Object)} instead. + * + * @param path + * @param data + */ void putRuntimeData(P path, D data); + void putOperationalData(P path, D data); + void putConfigurationData(P path, D data); + /** + * Use {@link #removeOperationalData(Object)} + * + * @param path + */ void removeRuntimeData(P path); - void removeConfigurationData(P path); - - public Map getUpdatedConfigurationData(); + void removeOperationalData(P path); - public Map getUpdatedOperationalData(); - - public Set

getRemovedConfigurationData(); - - public Set

getRemovedOperationalData(); + void removeConfigurationData(P path); /** * Initiates a two-phase commit of modification. diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java new file mode 100644 index 0000000000..f448d4e2ee --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java @@ -0,0 +1,16 @@ +package org.opendaylight.controller.md.sal.common.api.data; + +public interface DataStore extends // + DataReader, // + DataModificationTransactionFactory { + + @Override + public DataModification beginTransaction(); + + @Override + public D readConfigurationData(P path); + + @Override + public D readOperationalData(P path); + +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java new file mode 100644 index 0000000000..afe9e9921e --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java @@ -0,0 +1,10 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import org.opendaylight.yangtools.concepts.Immutable; + +public interface Route extends Immutable { + + C getType(); + + P getPath(); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java new file mode 100644 index 0000000000..994f65b960 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import java.util.EventListener; + +public interface RouteChangeListener extends EventListener { + + void onRouteChange(RouteChange change); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java new file mode 100644 index 0000000000..89851c9393 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import org.opendaylight.yangtools.concepts.ListenerRegistration; + +public interface RouteChangePublisher { + + ListenerRegistration> registerRouteChangeListener(RouteChangeListener listener); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java new file mode 100644 index 0000000000..8d0a90c50b --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java @@ -0,0 +1,10 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import java.util.Map; +import java.util.Set; + +public interface Router extends // + RouteChangePublisher { + + Map> getAnnouncedPaths(); +} diff --git a/opendaylight/md-sal/sal-common-impl/pom.xml b/opendaylight/md-sal/sal-common-impl/pom.xml index 0c2344a23e..3bd51ec7d8 100644 --- a/opendaylight/md-sal/sal-common-impl/pom.xml +++ b/opendaylight/md-sal/sal-common-impl/pom.xml @@ -37,7 +37,10 @@ maven-bundle-plugin - org.opendaylight.controller.md.sal.common.impl + + org.opendaylight.controller.md.sal.common.impl, + org.opendaylight.controller.md.sal.common.impl.* + diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java index 5d76717ab6..c335b75e15 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java @@ -5,68 +5,109 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.controller.md.sal.common.api.data.DataReader; import org.opendaylight.yangtools.concepts.Path; import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW; -public abstract class AbstractDataModification

*/, D> implements DataModification { +public abstract class AbstractDataModification

*/, D> implements DataModification { - private final Map configurationUpdate; - private final Map operationalUpdate; + private final ConcurrentMap operationalOriginal; + private final ConcurrentMap configurationOriginal; - private final Set

configurationRemove; - private final Set

operationalRemove; + private final ConcurrentMap operationalCreated; + private final ConcurrentMap configurationCreated; + private final ConcurrentMap configurationUpdate; + private final ConcurrentMap operationalUpdate; + + private final ConcurrentMap configurationRemove; + private final ConcurrentMap operationalRemove; + + private final Map unmodifiable_configurationOriginal; + private final Map unmodifiable_operationalOriginal; + private final Map unmodifiable_configurationCreated; + private final Map unmodifiable_operationalCreated; private final Map unmodifiable_configurationUpdate; private final Map unmodifiable_operationalUpdate; private final Set

unmodifiable_configurationRemove; private final Set

unmodifiable_OperationalRemove; + private DataReader reader; + + public AbstractDataModification(DataReader reader) { + this.reader = reader; + this.configurationUpdate = new ConcurrentHashMap<>(); + this.operationalUpdate = new ConcurrentHashMap<>(); + this.configurationRemove = new ConcurrentHashMap<>(); + this.operationalRemove = new ConcurrentHashMap<>(); - public AbstractDataModification(Map configurationUpdate, Map operationalUpdate, - Set

configurationRemove, Set

operationalRemove) { - this.configurationUpdate = configurationUpdate; - this.operationalUpdate = operationalUpdate; - this.configurationRemove = configurationRemove; - this.operationalRemove = operationalRemove; + this.configurationOriginal = new ConcurrentHashMap<>(); + this.operationalOriginal = new ConcurrentHashMap<>(); + this.configurationCreated = new ConcurrentHashMap<>(); + this.operationalCreated = new ConcurrentHashMap<>(); + + unmodifiable_configurationOriginal = Collections.unmodifiableMap(configurationOriginal); + unmodifiable_operationalOriginal = Collections.unmodifiableMap(operationalOriginal); + unmodifiable_configurationCreated = Collections.unmodifiableMap(configurationCreated); + unmodifiable_operationalCreated = Collections.unmodifiableMap(operationalCreated); unmodifiable_configurationUpdate = Collections.unmodifiableMap(configurationUpdate); unmodifiable_operationalUpdate = Collections.unmodifiableMap(operationalUpdate); - unmodifiable_configurationRemove = Collections.unmodifiableSet(configurationRemove); - unmodifiable_OperationalRemove = Collections.unmodifiableSet(operationalRemove); - } + unmodifiable_configurationRemove = Collections.unmodifiableSet(configurationRemove.keySet()); + unmodifiable_OperationalRemove = Collections.unmodifiableSet(operationalRemove.keySet()); - public AbstractDataModification() { - this(new HashMap(), new HashMap(), new HashSet

(), new HashSet

()); } @Override public final void putConfigurationData(P path, D data) { checkMutable(); + + if (!hasConfigurationOriginal(path)) { + configurationCreated.put(path, data); + } + configurationUpdate.put(path, data); configurationRemove.remove(path); } @Override - public final void putRuntimeData(P path, D data) { + public final void putOperationalData(P path, D data) { checkMutable(); + if (!hasOperationalOriginal(path)) { + operationalCreated.put(path, data); + } operationalUpdate.put(path, data); operationalRemove.remove(path); } @Override - public final void removeRuntimeData(P path) { + public final void putRuntimeData(P path, D data) { + putRuntimeData(path, data); + } + + @Override + public final void removeOperationalData(P path) { checkMutable(); + hasOperationalOriginal(path); operationalUpdate.remove(path); - operationalRemove.add(path); + operationalRemove.put(path, path); + } + + @Override + public final void removeRuntimeData(P path) { + removeOperationalData(path); } @Override public final void removeConfigurationData(P path) { checkMutable(); + hasConfigurationOriginal(path); configurationUpdate.remove(path); - configurationRemove.add(path); + configurationRemove.put(path, path); } private final void checkMutable() { @@ -75,24 +116,77 @@ public abstract class AbstractDataModification

*/, D> impleme } @Override - public Map getUpdatedConfigurationData() { + public final Map getUpdatedConfigurationData() { return unmodifiable_configurationUpdate; } @Override - public Map getUpdatedOperationalData() { + public final Map getUpdatedOperationalData() { return unmodifiable_operationalUpdate; } @Override - public Set

getRemovedConfigurationData() { + public final Set

getRemovedConfigurationData() { return unmodifiable_configurationRemove; } @Override - public Set

getRemovedOperationalData() { + public final Set

getRemovedOperationalData() { return unmodifiable_OperationalRemove; } + @Override + public Map getCreatedConfigurationData() { + return unmodifiable_configurationCreated; + } + + @Override + public Map getCreatedOperationalData() { + return unmodifiable_operationalCreated; + } + + @Override + public Map getOriginalConfigurationData() { + return unmodifiable_configurationOriginal; + } + + @Override + public Map getOriginalOperationalData() { + return unmodifiable_operationalOriginal; + } + + @Override + public D readOperationalData(P path) { + return reader.readOperationalData(path); + } + + @Override + public D readConfigurationData(P path) { + return reader.readConfigurationData(path); + } + + private boolean hasConfigurationOriginal(P path) { + if (configurationOriginal.containsKey(path)) { + return true; + } + D data = reader.readConfigurationData(path); + if (data != null) { + configurationOriginal.putIfAbsent(path, data); + return true; + } + return false; + } + + private boolean hasOperationalOriginal(P path) { + if (operationalOriginal.containsKey(path)) { + return true; + } + D data = reader.readConfigurationData(path); + if (data != null) { + operationalOriginal.putIfAbsent(path, data); + return true; + } + return false; + } } diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java new file mode 100644 index 0000000000..f83c61f804 --- /dev/null +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java @@ -0,0 +1,187 @@ +package org.opendaylight.controller.md.sal.common.impl.routing; + +import java.util.Map.Entry; + +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.concepts.Path; +import org.opendaylight.yangtools.concepts.Registration; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +/** + * Base abstract implementation of DataReadRouter, which performs + * a read operation on multiple data readers and then merges result. + * + * @param

+ * @param + */ +public abstract class AbstractDataReadRouter

, D> implements DataReader { + + Multimap> configReaders = HashMultimap.create(); + Multimap> operationalReaders = HashMultimap.create(); + + @Override + public D readConfigurationData(P path) { + FluentIterable dataBits = FluentIterable // + .from(getReaders(configReaders, path)).transform(configurationRead(path)); + return merge(path,dataBits); + } + + @Override + public D readOperationalData(P path) { + FluentIterable dataBits = FluentIterable // + .from(getReaders(configReaders, path)).transform(operationalRead(path)); + return merge(path,dataBits); + + } + + /** + * Merges data readed by reader instances from specified path + * + * @param path Path on which read was performed + * @param data Data which was returned by read operation. + * @return Merged result. + */ + protected abstract D merge(P path,Iterable data); + + /** + * Returns a function which performs configuration read for supplied path + * + * @param path + * @return function which performs configuration read for supplied path + */ + + private Function, D> configurationRead(final P path) { + return new Function, D>() { + @Override + public D apply(DataReader input) { + return input.readConfigurationData(path); + } + }; + } + + /** + * Returns a function which performs operational read for supplied path + * + * @param path + * @return function which performs operational read for supplied path + */ + private Function, D> operationalRead(final P path) { + return new Function, D>() { + @Override + public D apply(DataReader input) { + return input.readConfigurationData(path); + } + }; + } + + // Registrations + + /** + * Register's a reader for operational data. + * + * @param path Path which is served by this reader + * @param reader Reader instance which is responsible for reading particular subpath. + * @return + */ + public Registration> registerOperationalReader(P path, DataReader reader) { + OperationalDataReaderRegistration ret = new OperationalDataReaderRegistration<>(path, reader); + operationalReaders.put(path, ret); + return ret; + } + + public Registration> registerConfigurationReader(P path, DataReader reader) { + ConfigurationDataReaderRegistration ret = new ConfigurationDataReaderRegistration<>(path, reader); + configReaders.put(path, ret); + return ret; + } + + Iterable> getOperationalReaders(P path) { + return getReaders(operationalReaders, path); + } + + Iterable> getConfigurationReaders(P path) { + return getReaders(configReaders, path); + } + + private Iterable> getReaders(Multimap> readerMap, P path) { + return FluentIterable + .from(readerMap.entries()) // + .filter(affects(path)) // + .transform(retrieveInstance()); + } + + private void removeRegistration(OperationalDataReaderRegistration registration) { + operationalReaders.remove(registration.getKey(), registration); + } + + private void removeRegistration(ConfigurationDataReaderRegistration registration) { + configReaders.remove(registration.getKey(), registration); + } + + private Function>, DataReader> retrieveInstance() { + return new Function>, DataReader>() { + @Override + public DataReader apply(Entry> input) { + return input.getValue().getInstance(); + } + }; + } + + private Predicate>> affects(final P path) { + + return new Predicate>>() { + + @Override + public boolean apply(Entry> input) { + final Path key = input.getKey(); + return key.contains(path) || ((Path) path).contains(key); + } + + }; + } + + private class ConfigurationDataReaderRegistration

, D> extends DataReaderRegistration { + + public ConfigurationDataReaderRegistration(P key, DataReader instance) { + super(key, instance); + } + + @Override + protected void removeRegistration() { + AbstractDataReadRouter.this.removeRegistration(this); + } + } + + private class OperationalDataReaderRegistration

, D> extends DataReaderRegistration { + + public OperationalDataReaderRegistration(P key, DataReader instance) { + super(key, instance); + } + + @Override + protected void removeRegistration() { + AbstractDataReadRouter.this.removeRegistration(this); + } + } + + private abstract static class DataReaderRegistration

, D> extends + AbstractObjectRegistration> { + + private final P key; + + public P getKey() { + return this.key; + } + + public DataReaderRegistration(P key, DataReader instance) { + super(instance); + this.key = key; + } + } +} diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalPropertyClassUtils.java b/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalPropertyClassUtils.java new file mode 100644 index 0000000000..08df0a414a --- /dev/null +++ b/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalPropertyClassUtils.java @@ -0,0 +1,70 @@ +package org.opendaylight.controller.sal.compability; + +import org.opendaylight.controller.sal.core.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; + +public class ToSalPropertyClassUtils { + public static Bandwidth salAdvertisedBandwidthFrom(NodeConnector nodeConnector) { + FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class); + PortFeatures portFeatures = flowCapNodeConn.getAdvertisedFeatures(); + return new AdvertisedBandwidth(resolveBandwidth(portFeatures)); + } + + public static Bandwidth salPeerBandwidthFrom(NodeConnector nodeConnector) { + FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class); + PortFeatures portFeatures = flowCapNodeConn.getPeerFeatures(); + return new PeerBandwidth(resolveBandwidth(portFeatures)); + } + + public static Bandwidth salSupportedBandwidthFrom(NodeConnector nodeConnector) { + FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class); + PortFeatures portFeatures = flowCapNodeConn.getSupported(); + return new SupportedBandwidth(resolveBandwidth(portFeatures)); + } + + public static MacAddress salMacAddressFrom(NodeConnector nodeConnector) { + FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class); + String hwAddress = flowCapNodeConn.getHardwareAddress().getValue(); + return new MacAddress(bytesFrom(hwAddress)); + } + + + public static Name salNameFrom(NodeConnector nodeConnector) { + FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class); + return new Name(flowCapNodeConn.getName()); + } + + + + private static byte[] bytesFrom(String hwAddress) { + String[] mac = hwAddress.split(":"); + byte[] macAddress = new byte[6]; // mac.length == 6 bytes + for (int i = 0; i < mac.length; i++) { + macAddress[i] = Integer.decode("0x" + mac[i]).byteValue(); + } + return macAddress; + } + + private static long resolveBandwidth(PortFeatures portFeatures) { + if (portFeatures.is_1tbFd()) { + return Bandwidth.BW1Tbps; + } else if (portFeatures.is_100gbFd()) { + return Bandwidth.BW100Gbps; + } else if (portFeatures.is_40gbFd()) { + return Bandwidth.BW40Gbps; + } else if (portFeatures.is_10gbFd()) { + return Bandwidth.BW10Gbps; + } else if (portFeatures.is_1gbHd() || portFeatures.is_1gbFd()) { + return Bandwidth.BW1Gbps; + } else if (portFeatures.is_100mbHd() || portFeatures.is_100mbFd()) { + return Bandwidth.BW100Mbps; + } else if (portFeatures.is_10mbHd() || portFeatures.is_10mbFd()) { + return Bandwidth.BW10Mbps; + } else { + return Bandwidth.BWUNK; + } + } + +} diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowServiceAdapter.java b/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowServiceAdapter.java deleted file mode 100644 index 809ad76e5a..0000000000 --- a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowServiceAdapter.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.opendaylight.controller.sal.compability.adsal; - -import java.util.concurrent.Future; - -import org.opendaylight.controller.sal.binding.api.NotificationProviderService; -import org.opendaylight.controller.sal.common.util.Futures; -import org.opendaylight.controller.sal.common.util.Rpcs; -import org.opendaylight.controller.sal.compability.NodeMapping; -import org.opendaylight.controller.sal.compability.ToSalConversionsUtils; -import org.opendaylight.controller.sal.core.ConstructionException; -import org.opendaylight.controller.sal.core.Node; -import org.opendaylight.controller.sal.flowprogrammer.Flow; -import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener; -import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService; -import org.opendaylight.controller.sal.utils.Status; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListener { - - private static final Logger LOG = LoggerFactory.getLogger(FlowServiceAdapter.class); - - private IFlowProgrammerService delegate; - - private NotificationProviderService publish; - - @Override - public void flowRemoved(Node node, Flow flow) { - FlowRemovedBuilder flowRemovedBuilder = new FlowRemovedBuilder(); - flowRemovedBuilder.setNode(NodeMapping.toNodeRef(node)); - publish.publish(flowRemovedBuilder.build()); - } - - @Override - public void flowErrorReported(Node node, long rid, Object err) { - // TODO Auto-generated method stub - - } - - @Override - public Future> addFlow(AddFlowInput input) { - try { - Flow flow = ToSalConversionsUtils.toFlow(input); - Node node = NodeMapping.toADNode(input.getNode()); - Status status = delegate.addFlowAsync(node, flow); - Void rpcResultType = null; - return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); - } catch (ConstructionException e) { - LOG.error(e.getMessage()); - } - return null; - } - - @Override - public Future> removeFlow(RemoveFlowInput input) { - try { - Flow flow = ToSalConversionsUtils.toFlow(input); - Node node = NodeMapping.toADNode(input.getNode()); - Status status = delegate.removeFlowAsync(node, flow); - Void rpcResultType = null; - return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); - } catch (ConstructionException e) { - LOG.error(e.getMessage()); - } - return null; - } - - @Override - public Future> updateFlow(UpdateFlowInput input) { - try { - Node node = NodeMapping.toADNode(input.getNode()); - Flow originalFlow = ToSalConversionsUtils.toFlow(input.getOriginalFlow()); - Flow updatedFlow = ToSalConversionsUtils.toFlow(input.getUpdatedFlow()); - Status status = delegate.modifyFlowAsync(node, originalFlow, updatedFlow); - Void rpcResultType = null; - return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); - } catch (ConstructionException e) { - LOG.error(e.getMessage()); - } - return null; - } -} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java new file mode 100644 index 0000000000..c19ee1a7cb --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java @@ -0,0 +1,22 @@ +package org.opendaylight.controller.sal.core.api; + +import java.util.concurrent.Future; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public interface RpcConsumptionRegistry { + /** + * Sends an RPC to other components registered to the broker. + * + * @see RpcImplementation + * @param rpc + * Name of RPC + * @param input + * Input data to the RPC + * @return Result of the RPC call + */ + Future> rpc(QName rpc, CompositeNode input); + +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java new file mode 100644 index 0000000000..c326bab7a4 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java @@ -0,0 +1,33 @@ +package org.opendaylight.controller.sal.core.api; + +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; +import org.opendaylight.yangtools.yang.common.QName; + +public interface RpcProvisionRegistry { + + /** + * Registers an implementation of the rpc. + * + *

+ * The registered rpc functionality will be available to all other + * consumers and providers registered to the broker, which are aware of + * the {@link QName} assigned to the rpc. + * + *

+ * There is no assumption that rpc type is in the set returned by + * invoking {@link RpcImplementation#getSupportedRpcs()}. This allows + * for dynamic rpc implementations. + * + * @param rpcType + * Name of Rpc + * @param implementation + * Provider's Implementation of the RPC functionality + * @throws IllegalArgumentException + * If the name of RPC is invalid + */ + RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation) + throws IllegalArgumentException; + + RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation); +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java index 3024c89d61..20fa29dceb 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java @@ -10,8 +10,10 @@ package org.opendaylight.controller.sal.core.api.data; import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService; import org.opendaylight.controller.sal.common.DataStoreIdentifier; import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.DataReader;; public interface DataProviderService extends DataBrokerService, // @@ -54,6 +56,11 @@ public interface DataProviderService extends */ void removeRefresher(DataStoreIdentifier store, DataRefresher refresher); + + Registration> registerConfigurationReader(InstanceIdentifier path, DataReader reader); + + Registration> registerOperationalReader(InstanceIdentifier path, DataReader reader); + public interface DataRefresher extends Provider.ProviderFunctionality { /** diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java new file mode 100644 index 0000000000..8f6a5d0a90 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.sal.core.api.mount; + +import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; +import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService; + +public interface MountProvisionInstance extends MountInstance, NotificationPublishService, RpcProvisionRegistry { + +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java new file mode 100644 index 0000000000..fade7d341b --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.core.api.mount; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public interface MountProvisionService extends MountService { + + @Override + public MountProvisionInstance getMountPoint(InstanceIdentifier path); + + MountProvisionInstance createMountPoint(InstanceIdentifier path); + + MountProvisionInstance createOrGetMountPoint(InstanceIdentifier path); +} diff --git a/opendaylight/md-sal/sal-dom-broker/pom.xml b/opendaylight/md-sal/sal-dom-broker/pom.xml index 678728ab3b..9383a9e2ff 100644 --- a/opendaylight/md-sal/sal-dom-broker/pom.xml +++ b/opendaylight/md-sal/sal-dom-broker/pom.xml @@ -24,6 +24,11 @@ org.opendaylight.controller sal-common-util 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-impl + 1.0-SNAPSHOT org.opendaylight.controller @@ -60,7 +65,7 @@ ${project.groupId}.${project.artifactId} org.opendaylight.controller.sal.dom.broker.BrokerActivator - org.opendaylight.controller.sal.dom.broker, + org.opendaylight.controller.sal.dom.broker.* diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend index 83dda5902d..855ad9bd32 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend @@ -7,29 +7,28 @@ */ package org.opendaylight.controller.sal.dom.broker; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import org.opendaylight.controller.sal.core.api.Broker; -import org.opendaylight.controller.sal.core.api.BrokerService; -import org.opendaylight.controller.sal.core.api.Consumer; -import org.opendaylight.controller.sal.core.api.Provider; -import org.opendaylight.controller.sal.core.api.RpcImplementation; -import org.opendaylight.controller.sal.core.spi.BrokerModule; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.osgi.framework.BundleContext; -import org.slf4j.LoggerFactory; +import java.util.Collections +import java.util.HashMap +import java.util.HashSet +import java.util.Map +import java.util.Set +import java.util.concurrent.Callable +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import java.util.concurrent.Future +import org.opendaylight.controller.sal.core.api.Broker +import org.opendaylight.controller.sal.core.api.BrokerService +import org.opendaylight.controller.sal.core.api.Consumer +import org.opendaylight.controller.sal.core.api.Provider +import org.opendaylight.controller.sal.core.spi.BrokerModule +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.yangtools.yang.common.RpcResult +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import org.osgi.framework.BundleContext +import org.slf4j.LoggerFactory +import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter import org.opendaylight.yangtools.concepts.ListenerRegistration import org.opendaylight.controller.sal.core.api.RpcRegistrationListener -import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry public class BrokerImpl implements Broker { private static val log = LoggerFactory.getLogger(BrokerImpl); @@ -42,17 +41,14 @@ public class BrokerImpl implements Broker { private val Map, BrokerModule> serviceProviders = Collections. synchronizedMap(new HashMap, BrokerModule>()); - - private val rpcRegistrationListeners = new ListenerRegistry(); - // RPC Context - private val Map rpcImpls = Collections.synchronizedMap( - new HashMap()); - // Implementation specific @Property private var ExecutorService executor = Executors.newFixedThreadPool(5); @Property private var BundleContext bundleContext; + + @Property + private var RpcRouter router; override registerConsumer(Consumer consumer, BundleContext ctx) { checkPredicates(consumer); @@ -95,42 +91,8 @@ public class BrokerImpl implements Broker { return prov.getServiceForSession(service, session); } - // RPC Functionality - protected def void addRpcImplementation(QName rpcType, RpcImplementation implementation) { - if(rpcImpls.get(rpcType) != null) { - throw new IllegalStateException("Implementation for rpc " + rpcType + " is already registered."); - } - - - rpcImpls.put(rpcType, implementation); - - - for(listener : rpcRegistrationListeners.listeners) { - try { - listener.instance.onRpcImplementationAdded(rpcType); - } catch (Exception e){ - log.error("Unhandled exception during invoking listener",e); - } - } - } - - protected def void removeRpcImplementation(QName rpcType, RpcImplementation implToRemove) { - if(implToRemove == rpcImpls.get(rpcType)) { - rpcImpls.remove(rpcType); - } - - for(listener : rpcRegistrationListeners.listeners) { - try { - listener.instance.onRpcImplementationRemoved(rpcType); - } catch (Exception e){ - log.error("Unhandled exception during invoking listener",e); - } - } - } - protected def Future> invokeRpc(QName rpc, CompositeNode input) { - val impl = rpcImpls.get(rpc); - val result = executor.submit([|impl.invokeRpc(rpc, input)] as Callable>); + val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable>); return result; } @@ -171,12 +133,4 @@ public class BrokerImpl implements Broker { sessions.remove(consumerContextImpl); providerSessions.remove(consumerContextImpl); } - - protected def getSupportedRpcs() { - rpcImpls.keySet; - } - - def ListenerRegistration addRpcRegistrationListener(RpcRegistrationListener listener) { - rpcRegistrationListeners.register(listener); - } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java new file mode 100644 index 0000000000..7037b46ce9 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java @@ -0,0 +1,118 @@ +package org.opendaylight.controller.sal.dom.broker; + +import java.util.Set; +import java.util.concurrent.Future; + +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcRegistrationListener; +import org.opendaylight.controller.sal.core.api.data.DataChangeListener; +import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter; +import org.opendaylight.controller.sal.dom.broker.impl.NotificationRouterImpl; +import org.opendaylight.controller.sal.dom.broker.impl.RpcRouterImpl; +import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter; +import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public class MountPointImpl implements MountProvisionInstance { + + final RpcRouter rpcs; + final DataReaderRouter dataReader; + final NotificationRouter notificationRouter; + + public MountPointImpl(InstanceIdentifier path) { + rpcs = new RpcRouterImpl(""); + dataReader = new DataReaderRouter(); + notificationRouter = new NotificationRouterImpl(); + } + + @Override + public void publish(CompositeNode notification) { + notificationRouter.publish(notification); + } + + @Override + public Registration addNotificationListener(QName notification, NotificationListener listener) { + return notificationRouter.addNotificationListener(notification, listener); + } + + @Override + public CompositeNode readConfigurationData(InstanceIdentifier path) { + return dataReader.readConfigurationData(path); + } + + @Override + public CompositeNode readOperationalData(InstanceIdentifier path) { + return dataReader.readOperationalData(path); + } + + public Registration> registerOperationalReader( + InstanceIdentifier path, DataReader reader) { + return dataReader.registerOperationalReader(path, reader); + } + + public Registration> registerConfigurationReader( + InstanceIdentifier path, DataReader reader) { + return dataReader.registerConfigurationReader(path, reader); + } + + @Override + public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) { + return rpcs.addRoutedRpcImplementation(rpcType, implementation); + } + + @Override + public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation) + throws IllegalArgumentException { + return rpcs.addRpcImplementation(rpcType, implementation); + } + + public Set getSupportedRpcs() { + return rpcs.getSupportedRpcs(); + } + + + public RpcResult invokeRpc(QName rpc, CompositeNode input) { + return rpcs.invokeRpc(rpc, input); + } + + public ListenerRegistration addRpcRegistrationListener(RpcRegistrationListener listener) { + return rpcs.addRpcRegistrationListener(listener); + } + + + @Override + public Future> rpc(QName type, CompositeNode input) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataModificationTransaction beginTransaction() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ListenerRegistration registerDataChangeListener(InstanceIdentifier path, + DataChangeListener listener) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void sendNotification(CompositeNode notification) { + publish(notification); + + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend new file mode 100644 index 0000000000..c64d1e56dd --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend @@ -0,0 +1,35 @@ +package org.opendaylight.controller.sal.dom.broker + + +import org.opendaylight.controller.sal.core.api.mount.MountProvisionService +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier +import java.util.concurrent.ConcurrentMap +import java.util.concurrent.ConcurrentHashMap +import static com.google.common.base.Preconditions.*; + +class MountPointManagerImpl implements MountProvisionService { + + ConcurrentMap mounts = new ConcurrentHashMap(); + + override createMountPoint(InstanceIdentifier path) { + checkState(!mounts.containsKey(path),"Mount already created"); + val mount = new MountPointImpl(path); + mounts.put(path,mount); + } + + + override createOrGetMountPoint(InstanceIdentifier path) { + val mount = mounts.get(path); + if(mount === null) { + return createMountPoint(path) + } + return mount; + } + + + override getMountPoint(InstanceIdentifier path) { + mounts.get(path); + } + + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend index bffc570596..cf5d220943 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend @@ -1,25 +1,23 @@ package org.opendaylight.controller.sal.dom.broker -import java.util.Collections -import java.util.HashMap import org.opendaylight.controller.sal.core.api.Broker.ProviderSession import org.opendaylight.controller.sal.core.api.Provider import org.opendaylight.controller.sal.core.api.RpcImplementation import org.opendaylight.yangtools.yang.common.QName import org.osgi.framework.BundleContext -import org.opendaylight.yangtools.concepts.AbstractObjectRegistration import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration -import static java.util.Collections.* -import java.util.Collections -import java.util.HashMap import org.opendaylight.controller.sal.core.api.RpcRegistrationListener +import org.opendaylight.yangtools.concepts.Registration + +import java.util.Set +import java.util.HashSet class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession { @Property private val Provider provider; - private val rpcImpls = Collections.synchronizedMap(new HashMap()); + private val Set> registrations = new HashSet(); new(Provider provider, BundleContext ctx) { super(null, ctx); @@ -27,39 +25,22 @@ class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession } override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException { - if (rpcType == null) { - throw new IllegalArgumentException("rpcType must not be null"); - } - if (implementation == null) { - throw new IllegalArgumentException("Implementation must not be null"); - } - broker.addRpcImplementation(rpcType, implementation); - rpcImpls.put(rpcType, implementation); - - return new RpcRegistrationImpl(rpcType, implementation, this); + val origReg = broker.router.addRpcImplementation(rpcType, implementation); + val newReg = new RpcRegistrationWrapper(origReg); + registrations.add(newReg); + return newReg; } - def removeRpcImplementation(RpcRegistrationImpl implToRemove) throws IllegalArgumentException { - val localImpl = rpcImpls.get(implToRemove.type); - if (localImpl !== implToRemove.instance) { - throw new IllegalStateException("Implementation was not registered in this session"); - } - broker.removeRpcImplementation(implToRemove.type, localImpl); - rpcImpls.remove(implToRemove.type); + protected def removeRpcImplementation(RpcRegistrationWrapper implToRemove) throws IllegalArgumentException { + registrations.remove(implToRemove); } - + override close() { - removeAllRpcImlementations - super.close - } - - private def removeAllRpcImlementations() { - if (!rpcImpls.empty) { - for (entry : rpcImpls.entrySet) { - broker.removeRpcImplementation(entry.key, entry.value); - } - rpcImpls.clear + + for (reg : registrations) { + reg.close() } + super.close } override addMountedRpcImplementation(QName rpcType, RpcImplementation implementation) { @@ -71,30 +52,34 @@ class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession } override getSupportedRpcs() { - broker.getSupportedRpcs(); + broker.router.supportedRpcs; } override addRpcRegistrationListener(RpcRegistrationListener listener) { - broker.addRpcRegistrationListener(listener); + broker.router.addRpcRegistrationListener(listener); } } -class RpcRegistrationImpl extends AbstractObjectRegistration implements RpcRegistration { +class RpcRegistrationWrapper implements RpcRegistration { + @Property - val QName type + val RpcRegistration delegate - private var ProviderContextImpl context + new(RpcRegistration delegate) { + _delegate = delegate + } - new(QName type, RpcImplementation instance, ProviderContextImpl ctx) { - super(instance) - _type = type - context = ctx + override getInstance() { + delegate.instance } - override protected removeRegistration() { - context.removeRpcImplementation(this) - context = null + override close() { + delegate.close } + override getType() { + delegate.type + } } + diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend new file mode 100644 index 0000000000..1e0f3385cc --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.dom.broker.impl + +import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier +import org.opendaylight.yangtools.yang.data.api.CompositeNode + +class DataReaderRouter extends AbstractDataReadRouter { + + override protected merge(InstanceIdentifier path, Iterable data) { + return data.iterator.next + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java new file mode 100644 index 0000000000..6d7b600dbc --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.dom.broker.impl; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality; +import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService; +import org.opendaylight.controller.sal.core.api.notify.NotificationService; +import org.opendaylight.controller.sal.core.spi.BrokerModule; +import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; + +public class NotificationRouterImpl implements NotificationRouter { + private static Logger log = LoggerFactory.getLogger(NotificationRouterImpl.class); + + private Multimap> listeners = HashMultimap.create(); + + private void sendNotification(CompositeNode notification) { + QName type = notification.getNodeType(); + Collection> toNotify = listeners.get(type); + log.info("Publishing notification " + type); + + if (toNotify == null) { + // No listeners were registered - returns. + return; + } + + for (Registration listener : toNotify) { + try { + // FIXME: ensure that notification is immutable + listener.getInstance().onNotification(notification); + } catch (Exception e) { + log.error("Uncaught exception in NotificationListener", e); + } + } + + } + + @Override + public void publish(CompositeNode notification) { + sendNotification(notification); + } + + @Override + public Registration addNotificationListener(QName notification, NotificationListener listener) { + ListenerRegistration ret = new ListenerRegistration(notification, listener); + return ret; + } + + private class ListenerRegistration extends AbstractObjectRegistration { + + final QName type; + + public ListenerRegistration(QName type, NotificationListener instance) { + super(instance); + this.type = type; + } + + @Override + protected void removeRegistration() { + listeners.remove(type, this); + } + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend new file mode 100644 index 0000000000..d67697f849 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend @@ -0,0 +1,106 @@ +package org.opendaylight.controller.sal.dom.broker.impl + +import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter +import org.opendaylight.yangtools.concepts.Identifiable +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.controller.sal.core.api.RpcImplementation +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import static com.google.common.base.Preconditions.*; +import java.util.Map +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration +import java.util.concurrent.ConcurrentHashMap +import java.util.Set +import java.util.Collections +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration +import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry +import org.opendaylight.controller.sal.core.api.RpcRegistrationListener +import org.slf4j.LoggerFactory + +class RpcRouterImpl implements RpcRouter, Identifiable { + + static val log = LoggerFactory.getLogger(RpcRouterImpl) + + Map implementations = new ConcurrentHashMap(); + + @Property + val Set supportedRpcs = Collections.unmodifiableSet(implementations.keySet); + + private val rpcRegistrationListeners = new ListenerRegistry(); + + @Property + val String identifier; + + new(String name) { + _identifier = name; + } + + override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) { + } + + override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException { + checkNotNull(rpcType, "Rpc Type should not be null"); + checkNotNull(implementation, "Implementation should not be null."); + checkState(!implementations.containsKey(rpcType), "Provider for supplied rpc is already registered."); + val reg = new RpcRegistrationImpl(rpcType, implementation, this); + implementations.put(rpcType, reg) + + for (listener : rpcRegistrationListeners.listeners) { + try { + listener.instance.onRpcImplementationAdded(rpcType); + } catch (Exception e) { + log.error("Unhandled exception during invoking listener", e); + } + } + + return reg; + + } + + override invokeRpc(QName rpc, CompositeNode input) { + checkNotNull(rpc, "Rpc Type should not be null"); + + val impl = implementations.get(rpc); + checkState(impl !== null, "Provider for supplied rpc is not registered."); + + return impl.instance.invokeRpc(rpc, input); + } + + def remove(RpcRegistrationImpl impl) { + val existing = implementations.get(impl.type); + if (existing == impl) { + implementations.remove(impl.type); + } + for (listener : rpcRegistrationListeners.listeners) { + try { + listener.instance.onRpcImplementationRemoved(impl.type); + } catch (Exception e) { + log.error("Unhandled exception during invoking listener", e); + } + } + } + + override addRpcRegistrationListener(RpcRegistrationListener listener) { + rpcRegistrationListeners.register(listener); + } + +} + +class RpcRegistrationImpl extends AbstractObjectRegistration implements RpcRegistration { + + @Property + val QName type; + + @Property + var RpcRouterImpl router; + + new(QName type, RpcImplementation instance, RpcRouterImpl router) { + super(instance) + _type = type + _router = router + } + + override protected removeRegistration() { + router.remove(this); + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java new file mode 100644 index 0000000000..fc42d2ceb9 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java @@ -0,0 +1,21 @@ +package org.opendaylight.controller.sal.dom.broker.spi; + +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public interface NotificationRouter { + + void publish(CompositeNode notification); + + /** + * Registers a notification listener for supplied notification type. + * + * @param notification + * @param listener + */ + Registration addNotificationListener(QName notification, + NotificationListener listener); + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java new file mode 100644 index 0000000000..97c2a151ce --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java @@ -0,0 +1,27 @@ +package org.opendaylight.controller.sal.dom.broker.spi; + +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public interface RoutedRpcProcessor extends RpcImplementation { + + public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation); + + public Set getSupportedRpcs(); + + public QName getRpcType(); + + public RpcResult invokeRpc(QName rpc, CompositeNode input); + + Map getRoutes(); + + RpcImplementation getDefaultRoute(); + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java new file mode 100644 index 0000000000..6886f892c6 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java @@ -0,0 +1,31 @@ +package org.opendaylight.controller.sal.dom.broker.spi; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcRegistrationListener; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public interface RpcRouter extends RpcProvisionRegistry, RpcImplementation { + + @Override + public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation); + + @Override + public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation) + throws IllegalArgumentException; + + @Override + public Set getSupportedRpcs(); + + @Override + public RpcResult invokeRpc(QName rpc, CompositeNode input); + + ListenerRegistration addRpcRegistrationListener(RpcRegistrationListener listener); +} diff --git a/opendaylight/md-sal/sal-netconf-connector/pom.xml b/opendaylight/md-sal/sal-netconf-connector/pom.xml index c8bc71577d..57e4d858c1 100644 --- a/opendaylight/md-sal/sal-netconf-connector/pom.xml +++ b/opendaylight/md-sal/sal-netconf-connector/pom.xml @@ -6,6 +6,9 @@ sal-parent 1.0-SNAPSHOT + + 0.2.2-SNAPSHOT + sal-netconf-connector scm:git:ssh://git.opendaylight.org:29418/controller.git @@ -18,6 +21,150 @@ ${project.groupId} sal-connector-api + + ${project.groupId} + sal-common-util + 1.0-SNAPSHOT + + + org.eclipse.xtend + org.eclipse.xtend.lib + + + org.opendaylight.controller + netconf-client + 0.2.2-SNAPSHOT + + + org.opendaylight.yangtools + yang-data-impl + 0.5.9-SNAPSHOT + + + junit + junit + test + + + ${project.groupId} + yang-test + ${netconf.version} + test + + + ${project.groupId} + config-api + ${netconf.version} + test + + + ${project.groupId} + config-util + ${netconf.version} + test + + + ${project.groupId} + yang-store-api + ${netconf.version} + test + + + ${project.groupId} + netconf-api + ${netconf.version} + test + + + org.opendaylight.bgpcep + util + test + 0.3.0-SNAPSHOT + + + ${project.groupId} + netconf-client + test + ${netconf.version} + + + ${project.groupId} + config-netconf-connector + test + ${netconf.version} + + + ${project.groupId} + yang-test + test + ${netconf.version} + + + ${project.groupId} + config-manager + test + ${netconf.version} + + + ${project.groupId} + config-persister-impl + test + ${netconf.version} + + + ${project.groupId} + config-manager + test + test-jar + ${netconf.version} + + + ${project.groupId} + netconf-impl + test + ${netconf.version} + + + ${project.groupId} + netconf-mapping-api + test + ${netconf.version} + + + ${project.groupId} + netconf-util + test + test-jar + ${netconf.version} + + + ${project.groupId} + yang-store-impl + test + ${netconf.version} + + + ${project.groupId} + yang-store-impl + test + test-jar + ${netconf.version} + + + org.opendaylight.controller + logback-config + test + ${netconf.version} + + + org.mockito + mockito-all + test + + + org.slf4j + slf4j-api + bundle diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java index c32e350509..b4cf6c985b 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java @@ -45,7 +45,9 @@ final class TestUtils { } for (int i = 0; i < fileList.length; i++) { String fileName = fileList[i]; - testFiles.add(new File(testDir, fileName)); + if (new File(testDir, fileName).isDirectory() == false) { + testFiles.add(new File(testDir, fileName)); + } } return parser.parseYangModels(testFiles); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java new file mode 100644 index 0000000000..841f8e593a --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java @@ -0,0 +1,273 @@ +package org.opendaylight.controller.sal.restconf.impl.test; + +import static org.junit.Assert.*; + +import java.io.*; +import java.util.Set; +import java.util.regex.*; + +import javax.ws.rs.WebApplicationException; + +import org.junit.*; +import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider; +import org.opendaylight.controller.sal.restconf.impl.StructuredData; +import org.opendaylight.yangtools.yang.model.api.*; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public class YangAndXmlToJsonConversion { + + @Ignore + @Test + /** + * Test for simple yang types (leaf, list, leaf-list, container and various combination of them) + * + */ + public void simpleYangTypesTest() { + String jsonOutput = null; + + jsonOutput = convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml", + "/yang-to-json-conversion/simple-yang-types"); + +// jsonOutput = +// readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/output.json"); + + verifyJsonOutputForSimpleYangTypes(jsonOutput); + + } + + private void verifyJsonOutputForSimpleYangTypes(String jsonOutput) { + + assertTrue("First and last character has to be '{' and '}'", Pattern.compile("\\A\\{.*\\}\\z", Pattern.DOTALL) + .matcher(jsonOutput).matches()); + + String prefix = "\"(smptp:|)"; + + // subnodes of cont1 + String cont1 = prefix + "cont1\":\\{"; + testLeaf(cont1, "lf11", new String("lf"), jsonOutput, prefix); + testLeafList(cont1, "lflst11", jsonOutput, prefix, new Integer(55), new Integer(56), new Integer(57)); + testLeafList(cont1, "lflst12", jsonOutput, prefix, new String("lflst12 str1"), new String("lflst12 str2"), + new String("lflst12 str1")); + + // subnodes of lst111 + // first object of lst111 + String lst11 = cont1 + ".*" + prefix + "lst11\":\\[\\{"; + testLeaf(lst11, "lf111", new Integer(140), jsonOutput, prefix); + testLeaf(lst11, "lf112", new String("lf112 str"), jsonOutput, prefix); + + // subnodes of cont111 + String cont111 = lst11 + ".*" + prefix + "cont111\":\\{"; + testLeaf(cont111, "lf1111", new String("lf1111 str"), jsonOutput, prefix); + testLeafList(cont1, "lflst1111", jsonOutput, prefix, new Integer(2048), new Integer(1024), new Integer(4096)); + + // subnodes of lst1111 + String lst1111 = cont111 + ".*" + prefix + "lst1111\":\\[\\{"; + testLeaf(lst1111, "lf1111A", new String("lf1111A str11"), jsonOutput, prefix); + testLeaf(lst1111, "lf1111B", new Integer(4), jsonOutput, prefix); + testLeaf(lst1111, "lf1111A", new String("lf1111A str12"), jsonOutput, prefix); + testLeaf(lst1111, "lf1111B", new Integer(7), jsonOutput, prefix); + // :subnodes of lst1111 + // :subnodes of cont111 + // :first object of lst111 + + // second object of lst111 + testLeaf(lst11, "lf111", new Integer(141), jsonOutput, prefix); + testLeaf(lst11, "lf112", new String("lf112 str2"), jsonOutput, prefix); + + // subnodes of cont111 + testLeaf(cont111, "lf1111", new String("lf1111 str2"), jsonOutput, prefix); + testLeafList(cont1, "lflst1111", jsonOutput, prefix, new Integer(2049), new Integer(1025), new Integer(4097)); + + // subnodes of lst1111 + testLeaf(lst1111, "lf1111A", new String("lf1111A str21"), jsonOutput, prefix); + testLeaf(lst1111, "lf1111B", new Integer(5), jsonOutput, prefix); + testLeaf(lst1111, "lf1111A", new String("lf1111A str22"), jsonOutput, prefix); + testLeaf(lst1111, "lf1111B", new Integer(8), jsonOutput, prefix); + // :subnodes of lst111 + // :subnodes of cont111 + // :second object of lst111 + // :second object of lst111 + // :subnodes of cont1 + } + + private void testLeaf(String prevRegEx, String lstName, Object value, String jsonFile, String elementPrefix) { + String newValue = null; + if (value instanceof Integer) { + newValue = value.toString(); + } else if (value instanceof String) { + newValue = "\"" + value.toString() + "\""; + } + String lf = elementPrefix + lstName + "\":" + newValue; + assertTrue(">>\"" + lstName + "\":" + newValue + "<< is missing", + Pattern.compile(".*" + prevRegEx + ".*" + lf + ".*", Pattern.DOTALL).matcher(jsonFile).matches()); + + } + + private void testLeafList(String prevRegEx, String lflstName, String jsonFile, String elementPrefix, + Object... dataInList) { + // order of element in the list isn't defined :( + String lflstBegin = elementPrefix + lflstName + "\":\\["; + String lflstEnd = ".*\\],"; + assertTrue( + ">>\"" + lflstName + "\": [],<< is missing", + Pattern.compile(".*" + prevRegEx + ".*" + lflstBegin + lflstEnd + ".*", Pattern.DOTALL) + .matcher(jsonFile).matches()); + + for (Object obj : dataInList) { + testValueOfLeafList(prevRegEx, lflstBegin, obj, jsonFile); + } + } + + private void testValueOfLeafList(String prevRegEx, String lflstPrevRegEx, Object value, String jsonFile) { + String lflstData = null; + lflstData = regExForDataValueInList(value); + assertNotNull(lflstPrevRegEx + ": value doesn't have correct type.", lflstData); + assertTrue( + prevRegEx + ": data value >" + value + "< is missing.", + Pattern.compile(".*" + prevRegEx + ".*" + lflstPrevRegEx + lflstData + ".*", Pattern.DOTALL) + .matcher(jsonFile).matches()); + + } + + /** + * Data value can be first, inner, last or only one member of list + * + * @param dataValue + * @return + */ + private String regExForDataValueInList(Object dataValue) { + String newDataValue; + if (dataValue instanceof Integer) { + newDataValue = dataValue.toString(); + return "(" + newDataValue + "(,[0-9]+)+|([0-9]+,)+" + newDataValue + "(,[0-9]+)+|([0-9]+,)+" + newDataValue + + "|" + newDataValue + ")\\]"; + } else if (dataValue instanceof String) { + newDataValue = "\"" + dataValue.toString() + "\""; + return "(" + newDataValue + "(,\".+\")+|(\".+\",)+" + newDataValue + "(,\".+\")+|(\".+\",)+" + newDataValue + + "|" + newDataValue + ")\\]"; + } + return null; + } + + private String readJsonFromFile(String path) { + String fullPath = YangAndXmlToJsonConversion.class.getResource(path).getPath(); + assertNotNull("Path to file can't be null.", fullPath); + File file = new File(fullPath); + assertNotNull("File can't be null", file); + FileReader fileReader = null; + try { + fileReader = new FileReader(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + assertNotNull("File reader can't be null.", fileReader); + + StringBuilder strBuilder = new StringBuilder(); + char[] buffer = new char[1000]; + + while (true) { + int loadedCharNum; + try { + loadedCharNum = fileReader.read(buffer); + } catch (IOException e) { + break; + } + if (loadedCharNum == -1) { + break; + } + strBuilder.append(buffer, 0, loadedCharNum); + } + try { + fileReader.close(); + } catch (IOException e) { + System.out.println("The file wasn't closed"); + ; + } + String rawStr = strBuilder.toString(); + rawStr = rawStr.replace("\n", ""); + rawStr = rawStr.replace("\r", ""); + rawStr = rawStr.replace("\t", ""); + rawStr = removeSpaces(rawStr); + + return rawStr; + } + + private String removeSpaces(String rawStr) { + StringBuilder strBuilder = new StringBuilder(); + int i = 0; + int quoteCount = 0; + while (i < rawStr.length()) { + if (rawStr.substring(i, i + 1).equals("\"")) { + quoteCount++; + } + + if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) { + strBuilder.append(rawStr.charAt(i)); + } + i++; + } + + return strBuilder.toString(); + } + + private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) { + String jsonResult = null; + Set modules = null; + + try { + modules = TestUtils.loadModules(YangAndXmlToJsonConversion.class.getResource(yangPath).getPath()); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + assertNotNull("modules can't be null.", modules); + + InputStream xmlStream = YangAndXmlToJsonConversion.class.getResourceAsStream(xmlDataPath); + CompositeNode compositeNode = null; + try { + compositeNode = TestUtils.loadCompositeNode(xmlStream); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + assertNotNull("Composite node can't be null", compositeNode); + + StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE; + for (Module module : modules) { + for (DataSchemaNode dataSchemaNode : module.getChildNodes()) { + StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode); + ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream(); + try { + structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS); + } catch (WebApplicationException | IOException e) { + e.printStackTrace(); + } + assertFalse( + "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(), + byteArrayOS.toString().isEmpty()); + jsonResult = byteArrayOS.toString(); + try { + outputToFile(byteArrayOS); + } catch (IOException e) { + System.out.println("Output file wasn't cloased sucessfuly."); + } + } + } + return jsonResult; + } + + private void outputToFile(ByteArrayOutputStream outputStream) throws IOException { + FileOutputStream fileOS = null; + try { + String path = YangAndXmlToJsonConversion.class.getResource("/yang-to-json-conversion/xml").getPath(); + File outFile = new File(path + "/data.json"); + fileOS = new FileOutputStream(outFile); + try { + fileOS.write(outputStream.toByteArray()); + } catch (IOException e) { + e.printStackTrace(); + } + fileOS.close(); + } catch (FileNotFoundException e1) { + e1.printStackTrace(); + } + } +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/simple-yang-types.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/simple-yang-types.yang new file mode 100644 index 0000000000..760dbd73ed --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/simple-yang-types.yang @@ -0,0 +1,47 @@ +module simple-yang-types { + namespace "simple:yang:types"; + + prefix "smptp"; + revision 2013-11-5 { + description "Initial revision."; + } + + container cont1 { + leaf lf11 { + type string; + } + leaf-list lflst11 { + type int32; + } + leaf-list lflst12 { + type string; + } + list lst11 { + key lf111; + leaf lf111 { + type uint8; + } + leaf lf112 { + type string; + } + container cont111 { + leaf lf1111 { + type string; + } + leaf-list lflst1111 { + type int32; + } + list lst1111 { + leaf lf1111A { + type string; + } + leaf lf1111B { + type uint8; + } + } + } + } + + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json new file mode 100644 index 0000000000..e76e7bd9ef --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json @@ -0,0 +1,45 @@ +{ + "smptp:cont1": { + "lf11":"lf", + "lflst11": [55,56,57], + "lflst12": ["lflst12 str1", "lflst12 str2", "lflst12 str3"], + "lst11": [ + { + "lf111":140, + "lf112":"lf112 str", + "cont111": { + "lf1111":"lf1111 str", + "lflst1111": [2048, 1024, 4096], + "lst1111": [ + { + "lf1111A": "lf1111A str11", + "lf1111B": 4 + }, + { + "lf1111A": "lf1111A str12", + "lf1111B": 7 + } + ] + } + }, + { + "lf111":141, + "lf112":"lf112 str2", + "cont111": { + "lf1111":"lf1111 str2", + "lflst1111": [2049, 1025, 4097], + "lst1111": [ + { + "lf1111A": "lf1111A str21", + "lf1111B": 5 + }, + { + "lf1111A": "lf1111A str22", + "lf1111B": 8 + } + ] + } + } + ] + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/data.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/data.xml new file mode 100644 index 0000000000..b47987ca23 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/data.xml @@ -0,0 +1,45 @@ + + lf + 55 + 56 + 57 + lflst12 str1 + lflst12 str2 + lflst12 str3 + + 140 + lf112 str + + lf1111 str + 2048 + 1024 + 4096 + + lf1111A str11 + 4 + + + lf1111A str12 + 7 + + + + + 141 + lf112 str2 + + lf1111 str2 + 2049 + 1025 + 4097 + + lf1111A str21 + 5 + + + lf1111A str22 + 8 + + + + diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java index 18c8ce5d15..123c03e9a1 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java @@ -67,6 +67,8 @@ public class EditConfigTest { doNothing().when(provider).abortTestTransaction(any(ObjectName.class)); doReturn(mockOn).when(provider).getOrCreateTransaction(); + doNothing().when(provider).wipeTestTransaction(any(ObjectName.class)); + doReturn(configTransactionClient).when(configRegistry).getConfigTransactionClient(any(ObjectName.class)); doReturn("mockConfigTransactionClient").when(configTransactionClient).toString(); diff --git a/opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/editConfig.xml b/opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/editConfig.xml index 8ec1c8c069..8f6ec9c4c2 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/editConfig.xml +++ b/opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/editConfig.xml @@ -3,7 +3,7 @@ - replace + merge diff --git a/opendaylight/netconf/netconf-util/pom.xml b/opendaylight/netconf/netconf-util/pom.xml index 20603c4774..d6bf62413a 100644 --- a/opendaylight/netconf/netconf-util/pom.xml +++ b/opendaylight/netconf/netconf-util/pom.xml @@ -52,6 +52,10 @@ netty-handler ${netconf.netty.version} + + org.opendaylight.controller.thirdparty + ganymed + @@ -72,6 +76,7 @@ org.opendaylight.controller.config.stat, com.google.common.base, com.google.common.collect, + ch.ethz.ssh2, io.netty.buffer, io.netty.channel, io.netty.channel.socket, diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/SshHandler.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/SshHandler.java new file mode 100644 index 0000000000..b911989c64 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/SshHandler.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.ChannelPromise; +import java.io.IOException; +import java.net.SocketAddress; +import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker; +import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClient; +import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter; +import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket; + +/** + * Netty SSH handler class. Acts as interface between Netty and SSH library. All standard Netty message handling + * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter}; + */ +public class SshHandler extends ChannelOutboundHandlerAdapter { + private final VirtualSocket virtualSocket = new VirtualSocket(); + private final SshClientAdapter sshClientAdapter; + + public SshHandler(AuthenticationHandler authenticationHandler, Invoker invoker) throws IOException { + SshClient sshClient = new SshClient(virtualSocket, authenticationHandler); + this.sshClientAdapter = new SshClientAdapter(sshClient, invoker); + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx){ + if (ctx.channel().pipeline().get("socket") == null) { + ctx.channel().pipeline().addFirst("socket", virtualSocket); + } + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + if (ctx.channel().pipeline().get("socket") != null) { + ctx.channel().pipeline().remove("socket"); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + this.sshClientAdapter.write((String) msg); + } + + @Override + public void connect(final ChannelHandlerContext ctx, + SocketAddress remoteAddress, + SocketAddress localAddress, + ChannelPromise promise) throws Exception { + ctx.connect(remoteAddress, localAddress, promise); + + promise.addListener(new ChannelFutureListener() { + public void operationComplete(ChannelFuture channelFuture) throws Exception { + sshClientAdapter.start(ctx); + }} + ); + } + + @Override + public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { + sshClientAdapter.stop(promise); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/AuthenticationHandler.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/AuthenticationHandler.java new file mode 100644 index 0000000000..a0e82f8bac --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/AuthenticationHandler.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.authentication; + +import ch.ethz.ssh2.Connection; + +import java.io.IOException; + +/** + * Class providing authentication facility to SSH handler. + */ +public abstract class AuthenticationHandler { + public abstract void authenticate(Connection connection) throws IOException; +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/LoginPassword.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/LoginPassword.java new file mode 100644 index 0000000000..bb0d37899d --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/LoginPassword.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.authentication; + +import ch.ethz.ssh2.Connection; + +import java.io.IOException; + +/** + * Class Providing username/password authentication option to {@link org.opendaylight.controller.netconf.util.handler.ssh.SshHandler} + */ +public class LoginPassword extends AuthenticationHandler { + private final String username; + private final String password; + + public LoginPassword(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public void authenticate(Connection connection) throws IOException { + boolean isAuthenticated = connection.authenticateWithPassword(username, password); + + if (isAuthenticated == false) throw new IOException("Authentication failed."); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/Invoker.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/Invoker.java new file mode 100644 index 0000000000..12d1129daf --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/Invoker.java @@ -0,0 +1,36 @@ +package org.opendaylight.controller.netconf.util.handler.ssh.client; + +import java.io.IOException; + +/** + * Abstract class providing mechanism of invoking various SSH level services. + * Class is not allowed to be extended, as it provides its own implementations via instance initiators. + */ +public abstract class Invoker { + private boolean invoked = false; + + private Invoker(){} + + protected boolean isInvoked() { + return invoked; + } + + abstract void invoke(SshSession session) throws IOException; + + /** + * Invoker implementation to invokes subsystem SSH service. + * + * @param subsystem + * @return + */ + public static Invoker subsystem(final String subsystem) { + return new Invoker() { + @Override + void invoke(SshSession session) throws IOException { + if (isInvoked() == true) throw new IllegalStateException("Already invoked."); + + session.startSubSystem(subsystem); + } + }; + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClient.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClient.java new file mode 100644 index 0000000000..c43aa6f3e5 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClient.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.client; + +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.channel.Channel; +import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + + +/** + * Wrapper class around GANYMED SSH java library. + */ +public class SshClient { + private final VirtualSocket socket; + private final Map openSessions = new HashMap(); + private final AuthenticationHandler authenticationHandler; + private Connection connection; + + public SshClient(VirtualSocket socket, + AuthenticationHandler authenticationHandler) throws IOException { + this.socket = socket; + this.authenticationHandler = authenticationHandler; + } + + public SshSession openSession() throws IOException { + if(connection == null) connect(); + + Session session = connection.openSession(); + SshSession sshSession = new SshSession(session); + openSessions.put(openSessions.size(), sshSession); + + return sshSession; + } + + private void connect() throws IOException { + connection = new Connection(socket); + connection.connect(); + authenticationHandler.authenticate(connection); + } + + public void closeSession(SshSession session) { + if( session.getState() == Channel.STATE_OPEN + || session.getState() == Channel.STATE_OPENING) { + session.session.close(); + } + } + + public void close() { + for(SshSession session : openSessions.values()) closeSession(session); + + openSessions.clear(); + + if(connection != null) connection.close(); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClientAdapter.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClientAdapter.java new file mode 100644 index 0000000000..a50462e40d --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClientAdapter.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.client; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.atomic.AtomicBoolean; +import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocketException; + +/** + * Worker thread class. Handles all downstream and upstream events in SSH Netty pipeline. + */ +public class SshClientAdapter implements Runnable { + private final SshClient sshClient; + private final Invoker invoker; + + private SshSession session; + private InputStream stdOut; + private InputStream stdErr; + private OutputStream stdIn; + + private ChannelHandlerContext ctx; + private ChannelPromise disconnectPromise; + + private final AtomicBoolean stopRequested = new AtomicBoolean(false); + + private final Object lock = new Object(); + + public SshClientAdapter(SshClient sshClient, + Invoker invoker) { + this.sshClient = sshClient; + this.invoker = invoker; + } + + public void run() { + try { + session = sshClient.openSession(); + invoker.invoke(session); + + stdOut = session.getStdout(); + stdErr = session.getStderr(); + + synchronized(lock) { + stdIn = session.getStdin(); + } + + while (stopRequested.get() == false) { + byte[] readBuff = new byte[1024]; + int c = stdOut.read(readBuff); + + byte[] tranBuff = new byte[c]; + System.arraycopy(readBuff, 0, tranBuff, 0, c); + + ByteBuf byteBuf = Unpooled.buffer(c); + byteBuf.writeBytes(tranBuff); + ctx.fireChannelRead(byteBuf); + } + + } catch (VirtualSocketException e) { + // Netty closed connection prematurely. + // Just pass and move on. + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + sshClient.close(); + + synchronized (lock) { + if(disconnectPromise != null) ctx.disconnect(disconnectPromise); + } + } + } + + // TODO: needs rework to match netconf framer API. + public void write(String message) throws IOException { + synchronized (lock) { + if (stdIn == null) throw new IllegalStateException("StdIn not available"); + } + stdIn.write(message.getBytes()); + stdIn.flush(); + } + + public void stop(ChannelPromise promise) { + synchronized (lock) { + stopRequested.set(true); + disconnectPromise = promise; + } + } + + public void start(ChannelHandlerContext ctx) { + if(this.ctx != null) return; // context is already associated. + + this.ctx = ctx; + new Thread(this).start(); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshSession.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshSession.java new file mode 100644 index 0000000000..df400aa141 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshSession.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.client; + +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.StreamGobbler; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Wrapper class for proprietary SSH sessions implementations + */ +public class SshSession { + final Session session; + + public SshSession(Session session) { + this.session = session; + } + + public void execCommand(String cmd) throws IOException { + session.execCommand(cmd); + } + + public void execCommand(String cmd, String charsetName) throws IOException { + session.execCommand(cmd, charsetName); + } + + public void startShell() throws IOException { + session.startShell(); + } + + public void startSubSystem(String name) throws IOException { + session.startSubSystem(name); + } + + public int getState() { + return session.getState(); + } + + public InputStream getStdout() { + return new StreamGobbler(session.getStdout()); + } + + public InputStream getStderr() { + return session.getStderr(); + } + + public OutputStream getStdin() { + return session.getStdin(); + } + + public int waitUntilDataAvailable(long timeout) throws IOException { + return session.waitUntilDataAvailable(timeout); + } + + public int waitForCondition(int condition_set, long timeout) { + return session.waitForCondition(condition_set, timeout); + } + + public Integer getExitStatus() { + return session.getExitStatus(); + } + + public String getExitSignal() { + return session.getExitSignal(); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelInputStream.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelInputStream.java new file mode 100644 index 0000000000..07c81b0ccb --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelInputStream.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Class provides {@link InputStream} functionality to users of virtual socket. + */ +public class ChannelInputStream extends InputStream implements ChannelInboundHandler { + private final Object lock = new Object(); + private final ByteBuf bb = Unpooled.buffer(); + + @Override + public int read(byte b[], int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + int bytesRead = 1; + synchronized (lock) { + int c = read(); + + b[off] = (byte)c; + + if(this.bb.readableBytes() == 0) return bytesRead; + + int ltr = len-1; + ltr = (ltr <= bb.readableBytes()) ? ltr : bb.readableBytes(); + + bb.readBytes(b, 1, ltr); + bytesRead += ltr; + } + return bytesRead; + } + + @Override + public int read() throws IOException { + synchronized (lock) { + while (this.bb.readableBytes() == 0) { + try { + lock.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + return this.bb.readByte() & 0xFF; + } + } + + @Override + public int available() throws IOException { + synchronized (lock) { + return this.bb.readableBytes(); + } + } + + public void channelRegistered(ChannelHandlerContext ctx) + throws Exception { + ctx.fireChannelRegistered(); + } + + public void channelUnregistered(ChannelHandlerContext ctx) + throws Exception { + ctx.fireChannelUnregistered(); + } + + public void channelActive(ChannelHandlerContext ctx) + throws Exception { + ctx.fireChannelActive(); + } + + public void channelInactive(ChannelHandlerContext ctx) + throws Exception { + ctx.fireChannelInactive(); + } + + public void channelRead(ChannelHandlerContext ctx, Object o) + throws Exception { + synchronized(lock) { + this.bb.discardReadBytes(); + this.bb.writeBytes((ByteBuf) o); + lock.notifyAll(); + } + } + + public void channelReadComplete(ChannelHandlerContext ctx) + throws Exception { + ctx.fireChannelReadComplete(); + } + + public void userEventTriggered(ChannelHandlerContext ctx, Object o) + throws Exception { + ctx.fireUserEventTriggered(o); + } + + public void channelWritabilityChanged(ChannelHandlerContext ctx) + throws Exception { + ctx.fireChannelWritabilityChanged(); + } + + public void handlerAdded(ChannelHandlerContext ctx) + throws Exception { + } + + public void handlerRemoved(ChannelHandlerContext ctx) + throws Exception { + } + + public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) + throws Exception { + ctx.fireExceptionCaught(throwable); + } +} + diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelOutputStream.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelOutputStream.java new file mode 100644 index 0000000000..b1314a6eed --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelOutputStream.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelOutboundHandler; +import io.netty.channel.ChannelPromise; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.SocketAddress; + +/** + * Class provides {@link OutputStream) functionality to users of virtual socket. + */ +public class ChannelOutputStream extends OutputStream implements ChannelOutboundHandler { + private final Object lock = new Object(); + private ByteBuf buff = Unpooled.buffer(); + private ChannelHandlerContext ctx; + + @Override + public void flush() throws IOException { + synchronized(lock) { + ctx.writeAndFlush(buff).awaitUninterruptibly(); + buff = Unpooled.buffer(); + } + } + + @Override + public void write(int b) throws IOException { + synchronized(lock) { + buff.writeByte(b); + } + } + + public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, + ChannelPromise promise) throws Exception { + ctx.bind(localAddress, promise); + } + + public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, + SocketAddress localAddress, ChannelPromise promise) + throws Exception { + this.ctx = ctx; + ctx.connect(remoteAddress, localAddress, promise); + } + + public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) + throws Exception { + ctx.disconnect(promise); + } + + public void close(ChannelHandlerContext ctx, ChannelPromise promise) + throws Exception { + ctx.close(promise); + } + + public void deregister(ChannelHandlerContext ctx, ChannelPromise channelPromise) + throws Exception { + ctx.deregister(channelPromise); + } + + public void read(ChannelHandlerContext ctx) + throws Exception { + ctx.read(); + } + + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) + throws Exception { + // pass + } + + public void flush(ChannelHandlerContext ctx) + throws Exception { + // pass + } + + public void handlerAdded(ChannelHandlerContext ctx) + throws Exception { + } + + public void handlerRemoved(ChannelHandlerContext ctx) + throws Exception { + } + + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) + throws Exception { + ctx.fireExceptionCaught(cause); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocket.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocket.java new file mode 100644 index 0000000000..1011ca16be --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocket.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.nio.channels.SocketChannel; + +/** + * Handler class providing Socket functionality to OIO client application. By using VirtualSocket user can + * use OIO application in asynchronous environment and NIO EventLoop. Using VirtualSocket OIO applications + * are able to use full potential of NIO environment. + */ +public class VirtualSocket extends Socket implements ChannelHandler { + private final ChannelInputStream chis = new ChannelInputStream(); + private final ChannelOutputStream chos = new ChannelOutputStream(); + private ChannelHandlerContext ctx; + + + public InputStream getInputStream() { + return this.chis; + } + + public OutputStream getOutputStream() { + return this.chos; + } + + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + this.ctx = ctx; + + if (ctx.channel().pipeline().get("outputStream") == null) { + ctx.channel().pipeline().addFirst("outputStream", chos); + } + + if (ctx.channel().pipeline().get("inputStream") == null) { + ctx.channel().pipeline().addFirst("inputStream", chis); + } + } + + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + if (ctx.channel().pipeline().get("outputStream") != null) { + ctx.channel().pipeline().remove("outputStream"); + } + + if (ctx.channel().pipeline().get("inputStream") != null) { + ctx.channel().pipeline().remove("inputStream"); + } + } + + public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) throws Exception { + ctx.fireExceptionCaught(throwable); + } + + public VirtualSocket() {super();} + + @Override + public void connect(SocketAddress endpoint) throws IOException {} + + @Override + public void connect(SocketAddress endpoint, int timeout) throws IOException {} + + @Override + public void bind(SocketAddress bindpoint) throws IOException {} + + @Override + public InetAddress getInetAddress() { + InetSocketAddress isa = getInetSocketAddress(); + + if (isa == null) throw new VirtualSocketException(); + + return getInetSocketAddress().getAddress(); + } + + @Override + public InetAddress getLocalAddress() {return null;} + + @Override + public int getPort() { + return getInetSocketAddress().getPort(); + } + + private InetSocketAddress getInetSocketAddress() { + return (InetSocketAddress)getRemoteSocketAddress(); + } + + @Override + public int getLocalPort() {return -1;} + + @Override + public SocketAddress getRemoteSocketAddress() { + return this.ctx.channel().remoteAddress(); + } + + @Override + public SocketAddress getLocalSocketAddress() { + return this.ctx.channel().localAddress(); + } + + @Override + public SocketChannel getChannel() {return null;} + + @Override + public void setTcpNoDelay(boolean on) throws SocketException {} + + @Override + public boolean getTcpNoDelay() throws SocketException {return false;} + + @Override + public void setSoLinger(boolean on, int linger) throws SocketException {} + + @Override + public int getSoLinger() throws SocketException {return -1;} + + @Override + public void sendUrgentData(int data) throws IOException {} + + @Override + public void setOOBInline(boolean on) throws SocketException {} + + @Override + public boolean getOOBInline() throws SocketException {return false;} + + @Override + public synchronized void setSoTimeout(int timeout) throws SocketException {} + + @Override + public synchronized int getSoTimeout() throws SocketException {return -1;} + + @Override + public synchronized void setSendBufferSize(int size) throws SocketException {} + + @Override + public synchronized int getSendBufferSize() throws SocketException {return -1;} + + @Override + public synchronized void setReceiveBufferSize(int size) throws SocketException {} + + @Override + public synchronized int getReceiveBufferSize() throws SocketException {return -1;} + + @Override + public void setKeepAlive(boolean on) throws SocketException {} + + @Override + public boolean getKeepAlive() throws SocketException {return false;} + + @Override + public void setTrafficClass(int tc) throws SocketException {} + + @Override + public int getTrafficClass() throws SocketException {return -1;} + + @Override + public void setReuseAddress(boolean on) throws SocketException {} + + @Override + public boolean getReuseAddress() throws SocketException {return false;} + + @Override + public synchronized void close() throws IOException {} + + @Override + public void shutdownInput() throws IOException {} + + @Override + public void shutdownOutput() throws IOException {} + + @Override + public String toString() { + return "Virtual socket InetAdress["+getInetAddress()+"], Port["+getPort()+"]"; + } + + @Override + public boolean isConnected() {return false;} + + @Override + public boolean isBound() {return false;} + + @Override + public boolean isClosed() {return false;} + + @Override + public boolean isInputShutdown() {return false;} + + @Override + public boolean isOutputShutdown() {return false;} + + @Override + public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {} +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocketException.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocketException.java new file mode 100644 index 0000000000..46fdbb83e7 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocketException.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket; + +/** + * Exception class which provides notification about exceptional situations at the virtual socket layer. + */ +public class VirtualSocketException extends RuntimeException { +} diff --git a/opendaylight/netconf/pom.xml b/opendaylight/netconf/pom.xml index 8f69f8dca0..5447f7f5d0 100644 --- a/opendaylight/netconf/pom.xml +++ b/opendaylight/netconf/pom.xml @@ -26,6 +26,7 @@ config-persister-impl netconf-mapping-api netconf-client + ../../third-party/ganymed diff --git a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java index 577c039530..189476a5d1 100644 --- a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java +++ b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java @@ -127,10 +127,20 @@ public class SubnetConfig implements Cloneable, Serializable { return new Status(StatusCode.SUCCESS); } + private Status validateName() { + if (name == null || name.trim().isEmpty()) { + return new Status(StatusCode.BADREQUEST, "Invalid name"); + } + return new Status(StatusCode.SUCCESS); + } + public Status validate() { - Status status = validateSubnetAddress(); + Status status = validateName(); if (status.isSuccess()) { - status = validatePorts(this.nodeConnectors); + status = validateSubnetAddress(); + if (status.isSuccess()) { + status = validatePorts(this.nodeConnectors); + } } return status; } diff --git a/opendaylight/web/devices/pom.xml b/opendaylight/web/devices/pom.xml index 38fef96a8c..f5605eaffe 100644 --- a/opendaylight/web/devices/pom.xml +++ b/opendaylight/web/devices/pom.xml @@ -32,9 +32,11 @@ org.opendaylight.controller.forwardingrulesmanager, org.opendaylight.controller.sal.authorization, org.opendaylight.controller.sal.action, + org.opendaylight.controller.sal.connection, org.opendaylight.controller.sal.core, org.opendaylight.controller.sal.utils, org.opendaylight.controller.containermanager, + org.opendaylight.controller.connectionmanager, org.opendaylight.controller.switchmanager, org.opendaylight.controller.forwarding.staticrouting, org.opendaylight.controller.usermanager, @@ -95,6 +97,11 @@ forwardingrulesmanager 0.4.1-SNAPSHOT + + org.opendaylight.controller + connectionmanager + 0.1.1-SNAPSHOT + org.opendaylight.controller containermanager diff --git a/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java b/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java index 6bde9d7c93..91261f6499 100644 --- a/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java +++ b/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java @@ -12,6 +12,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -23,10 +24,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.codehaus.jackson.map.ObjectMapper; +import org.opendaylight.controller.connectionmanager.IConnectionManager; import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting; import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig; import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.authorization.UserLevel; +import org.opendaylight.controller.sal.connection.ConnectionConstants; import org.opendaylight.controller.sal.core.Config; import org.opendaylight.controller.sal.core.Description; import org.opendaylight.controller.sal.core.ForwardingMode; @@ -38,8 +41,10 @@ import org.opendaylight.controller.sal.core.State; import org.opendaylight.controller.sal.core.Tier; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.HexEncode; +import org.opendaylight.controller.sal.utils.NetUtils; import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.sal.utils.TierHelper; import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.switchmanager.SpanConfig; @@ -49,6 +54,7 @@ import org.opendaylight.controller.switchmanager.SwitchConfig; import org.opendaylight.controller.web.DaylightWebUtil; import org.opendaylight.controller.web.IDaylightWeb; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -729,6 +735,94 @@ public class Devices implements IDaylightWeb { return resultBean; } + @RequestMapping(value = "/connect/nodes", method = RequestMethod.GET) + @ResponseBody + public List getNodes(HttpServletRequest request) { + IConnectionManager connectionManager = (IConnectionManager) ServiceHelper.getGlobalInstance( + IConnectionManager.class, this); + if (connectionManager == null) { + return null; + } + ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, + GlobalConstants.DEFAULT.toString(), this); + if (switchManager == null) { + return null; + } + + Set nodes = connectionManager.getLocalNodes(); + List result = new LinkedList(); + for (Node node : nodes) { + Description descriptionProperty = (Description) switchManager.getNodeProp(node, "description"); + String description = descriptionProperty.getValue(); + NodeJsonBean nodeBean = new NodeJsonBean(); + nodeBean.setNodeId(node.getNodeIDString()); + nodeBean.setNodeType(node.getType()); + if (description.equals("None")) { + nodeBean.setNodeName(node.toString()); + } else { + nodeBean.setNodeName(description); + } + result.add(nodeBean); + } + + return result; + } + + @RequestMapping(value = "/connect/{nodeId}", method = RequestMethod.POST) + @ResponseBody + public Status addNode(HttpServletRequest request, @PathVariable("nodeId") String nodeId, + @RequestParam(required = true) String ipAddress, @RequestParam(required = true) String port, + @RequestParam(required = false) String nodeType) { + IConnectionManager connectionManager = (IConnectionManager) ServiceHelper.getGlobalInstance( + IConnectionManager.class, this); + if (connectionManager == null) { + return new Status(StatusCode.NOTFOUND, "Service not found"); + } + + if (!NetUtils.isIPv4AddressValid(ipAddress)) { + return new Status(StatusCode.NOTACCEPTABLE, "Invalid IP Address: " + ipAddress); + } + + try { + Integer.parseInt(port); + } catch (Exception e) { + return new Status(StatusCode.NOTACCEPTABLE, "Invalid Layer 4 Port: " + port); + } + + Map params = new HashMap(); + params.put(ConnectionConstants.ADDRESS, ipAddress); + params.put(ConnectionConstants.PORT, port); + + Node node = null; + if (nodeType != null) { + node = connectionManager.connect(nodeType, nodeId, params); + } else { + node = connectionManager.connect(nodeId, params); + } + if (node == null) { + return new Status(StatusCode.NOTFOUND, "Failed to connect to Node at " + ipAddress + ":" + port); + } + return new Status(StatusCode.SUCCESS); + } + + @RequestMapping(value = "/disconnect/{nodeId}", method = RequestMethod.POST) + @ResponseBody + public Status removeNode(HttpServletRequest request, @PathVariable("nodeId") String nodeId, + @RequestParam(required = true) String nodeType) { + IConnectionManager connectionManager = (IConnectionManager) ServiceHelper.getGlobalInstance( + IConnectionManager.class, this); + if (connectionManager == null) { + return new Status(StatusCode.NOTFOUND, "Service not found"); + } + + try { + Node node = new Node(nodeType, nodeId); + return connectionManager.disconnect(node); + } catch (Exception e) { + return new Status(StatusCode.NOTFOUND, "Resource not found"); + } + } + private String getNodeDesc(String nodeId, String containerName) { ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this); diff --git a/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/NodeJsonBean.java b/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/NodeJsonBean.java index 61d4f2f91a..e5f2b6a2c0 100644 --- a/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/NodeJsonBean.java +++ b/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/NodeJsonBean.java @@ -13,6 +13,7 @@ import java.util.List; public class NodeJsonBean { String nodeId; String nodeName; + String nodeType; List nodePorts; public String getNodeId() { @@ -23,6 +24,10 @@ public class NodeJsonBean { return nodeName; } + public String getNodeType() { + return nodeType; + } + public List getNodePorts() { return nodePorts; } @@ -35,6 +40,10 @@ public class NodeJsonBean { this.nodeName = nodeName; } + public void setNodeType(String nodeType) { + this.nodeType = nodeType; + } + public void setNodePorts(List port) { this.nodePorts = port; } diff --git a/opendaylight/web/devices/src/main/resources/js/page.js b/opendaylight/web/devices/src/main/resources/js/page.js index b02a15a7e5..cc142bf967 100644 --- a/opendaylight/web/devices/src/main/resources/js/page.js +++ b/opendaylight/web/devices/src/main/resources/js/page.js @@ -12,1577 +12,1796 @@ one.f = {}; // specify dashlets and layouts one.f.dashlet = { - nodesLearnt : { - id : 'nodesLearnt', - name : 'Nodes Learned' - }, - staticRouteConfig : { - id : 'staticRouteConfig', - name : 'Static Route Configuration' - }, - subnetGatewayConfig : { - id : 'subnetGatewayConfig', - name : 'Subnet Gateway Configuration' - }, - spanPortConfig : { - id : 'spanPortConfig', - name : 'SPAN Port Configuration' - } + nodesLearnt : { + id : 'nodesLearnt', + name : 'Nodes Learned' + }, + staticRouteConfig : { + id : 'staticRouteConfig', + name : 'Static Route Configuration' + }, + subnetGatewayConfig : { + id : 'subnetGatewayConfig', + name : 'Subnet Gateway Configuration' + }, + spanPortConfig : { + id : 'spanPortConfig', + name : 'SPAN Port Configuration' + }, + connection : { + id : 'connection', + name : 'Connection Manager' + } }; one.f.menu = { - left : { - top : [ - one.f.dashlet.nodesLearnt - ], - bottom : [ - one.f.dashlet.staticRouteConfig - ] - }, - right : { - top : [], - bottom : [ - one.f.dashlet.subnetGatewayConfig, - one.f.dashlet.spanPortConfig - ] - } + left : { + top : [ + one.f.dashlet.nodesLearnt, + one.f.dashlet.connection + ], + bottom : [ + one.f.dashlet.staticRouteConfig + ] + }, + right : { + top : [], + bottom : [ + one.f.dashlet.subnetGatewayConfig, + one.f.dashlet.spanPortConfig + ] + } }; /**Devices Modules */ one.f.switchmanager = { - rootUrl: "controller/web/devices", - createTable: function(columnNames, body) { - var tableAttributes = ["table-striped", "table-bordered", "table-condensed"]; - var $table = one.lib.dashlet.table.table(tableAttributes); - var tableHeaders = columnNames; - var $thead = one.lib.dashlet.table.header(tableHeaders); - var $tbody = one.lib.dashlet.table.body(body, tableHeaders); - $table.append($thead) - .append($tbody); - return $table; - }, - validateName: function(name) { - return (name.length < 256); - } + rootUrl: "controller/web/devices", + createTable: function(columnNames, body) { + var tableAttributes = ["table-striped", "table-bordered", "table-condensed"]; + var $table = one.lib.dashlet.table.table(tableAttributes); + var tableHeaders = columnNames; + var $thead = one.lib.dashlet.table.header(tableHeaders); + var $tbody = one.lib.dashlet.table.body(body, tableHeaders); + $table.append($thead) + .append($tbody); + return $table; + }, + validateName: function(name) { + return (name.length < 256); + } }; one.f.switchmanager.nodesLearnt = { - id: { - dashlet: { - popout: "one_f_switchmanager_nodesLearnt_id_dashlet_popout", - datagrid: "one_f_switchmanager_nodesLearnt_id_dashlet_datagrid" - }, - modal: { - modal: "one_f_switchmanager_nodesLearnt_id_modal_modal", - configure: "one_f_switchmanager_nodesLearnt_id_modal_configure", - ports: "one_f_switchmanager_nodesLearnt_id_modal_ports", - save: "one_f_switchmanager_nodesLearnt_id_modal_save", - datagrid: "one_f_switchmanager_nodesLearnt_id_modal_datagrid", - portsDatagrid: "one_f_switchmanager_nodesLearnt_id_modal_portsDatagrid", - form: { - nodeId: "one_f_switchmanager_nodesLearnt_id_modal_form_nodeid", - nodeName : "one_f_switchmanager_nodesLearnt_id_modal_form_nodename", - portStatus : "one_f_switchmanager_nodesLearnt_id_modal_form_portstatus", - tier: "one_f_switchmanager_nodesLearnt_id_modal_form_tier", - operationMode: "one_f_switchmanager_nodesLearnt_id_modal_form_opmode" - } - } + id: { + dashlet: { + popout: "one_f_switchmanager_nodesLearnt_id_dashlet_popout", + datagrid: "one_f_switchmanager_nodesLearnt_id_dashlet_datagrid" }, - dashlet: function($dashlet) { - var url = one.f.switchmanager.rootUrl + "/nodesLearnt"; - one.lib.dashlet.empty($dashlet); - $dashlet.append(one.lib.dashlet.header(one.f.dashlet.nodesLearnt.name)); - - one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) { - var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.dashlet.datagrid, { - searchable: true, - filterable: false, - pagination: true, - flexibleRowsPerPage: true - }, "table-striped table-condensed"); - $dashlet.append($gridHTML); - var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.abridged(content); - $("#" + one.f.switchmanager.nodesLearnt.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() { - $(this).find("tbody a").click(one.f.switchmanager.nodesLearnt.modal.initialize.updateNode); - }); - - $("#" + one.f.switchmanager.nodesLearnt.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() { - $(this).find("tbody span").click(function(){ - one.f.switchmanager.nodesLearnt.modal.initialize.displayPorts($(this)); - }); - }); - + modal: { + modal: "one_f_switchmanager_nodesLearnt_id_modal_modal", + configure: "one_f_switchmanager_nodesLearnt_id_modal_configure", + ports: "one_f_switchmanager_nodesLearnt_id_modal_ports", + save: "one_f_switchmanager_nodesLearnt_id_modal_save", + datagrid: "one_f_switchmanager_nodesLearnt_id_modal_datagrid", + portsDatagrid: "one_f_switchmanager_nodesLearnt_id_modal_portsDatagrid", + form: { + nodeId: "one_f_switchmanager_nodesLearnt_id_modal_form_nodeid", + nodeName : "one_f_switchmanager_nodesLearnt_id_modal_form_nodename", + portStatus : "one_f_switchmanager_nodesLearnt_id_modal_form_portstatus", + tier: "one_f_switchmanager_nodesLearnt_id_modal_form_tier", + operationMode: "one_f_switchmanager_nodesLearnt_id_modal_form_opmode" + } + } + }, + dashlet: function($dashlet) { + var url = one.f.switchmanager.rootUrl + "/nodesLearnt"; + one.lib.dashlet.empty($dashlet); + $dashlet.append(one.lib.dashlet.header(one.f.dashlet.nodesLearnt.name)); + + one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) { + var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.dashlet.datagrid, { + searchable: true, + filterable: false, + pagination: true, + flexibleRowsPerPage: true + }, "table-striped table-condensed"); + $dashlet.append($gridHTML); + var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.abridged(content); + $("#" + one.f.switchmanager.nodesLearnt.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() { + $(this).find("tbody a").click(one.f.switchmanager.nodesLearnt.modal.initialize.updateNode); + }); + + $("#" + one.f.switchmanager.nodesLearnt.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() { + $(this).find("tbody span").click(function(){ + one.f.switchmanager.nodesLearnt.modal.initialize.displayPorts($(this)); }); + }); + + }); + }, + ajax : { + main : function(url, callback) { + $.getJSON(url, function(data) { + callback(data); + }); + } + }, + modal : { + initialize: { + updateNode: function(evt) { + one.f.switchmanager.nodesLearnt.ajax.main(one.f.switchmanager.rootUrl + "/tiers", function(tiers) { + + var nodeId = decodeURIComponent(evt.target.id); + var h3; + var footer = []; + var $body = one.f.switchmanager.nodesLearnt.modal.body.updateNode(nodeId, JSON.parse(decodeURIComponent(evt.target.getAttribute("switchDetails"))), tiers); + if (evt.target.getAttribute("privilege") == 'WRITE'){ + h3 = "Update Node Information"; + footer = one.f.switchmanager.nodesLearnt.modal.footer.updateNode(); + } else { //disable node edit + $body.find('*').attr('disabled', 'disabled'); + h3 = 'Node Information'; + } + + var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.configure, h3, "", footer); + // bind save button + $('#' + one.f.switchmanager.nodesLearnt.id.modal.save, $modal).click(function() { + one.f.switchmanager.nodesLearnt.modal.save($modal); + }); + + // inject body (nodePorts) + one.lib.modal.inject.body($modal, $body); + $modal.modal(); + }); + }, + popout: function() { + var h3 = "Nodes Learned"; + var footer = one.f.switchmanager.nodesLearnt.modal.footer.popout(); + var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.modal, h3, "", footer); + var $body = one.f.switchmanager.nodesLearnt.modal.body.popout($modal); + return $modal; + }, + displayPorts: function(ports) { + var content = JSON.parse(decodeURIComponent(ports.attr("ports"))); + + var h3 = ((ports.attr("nodeName") == "None")? ports.attr("nodeId") : ports.attr("nodeName")) + var footer = []; + var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.ports, h3, "", footer); + + var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.modal.portsDatagrid, { + searchable: true, + filterable: false, + pagination: true, + flexibleRowsPerPage: true, + popout: true + }, "table-striped table-condensed"); + one.lib.modal.inject.body($modal, $gridHTML); + $modal.on("shown", function() { + var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.displayPorts(content); + $("#" + one.f.switchmanager.nodesLearnt.id.modal.portsDatagrid).datagrid({ + dataSource: dataSource, + stretchHeight: false + }); + }); + $modal.modal(); + } }, - ajax : { - main : function(url, callback) { - $.getJSON(url, function(data) { - callback(data); - }); + body: { + updateNode: function(nodeId, switchDetails, tiers) { + var $form = $(document.createElement('form')); + var $fieldset = $(document.createElement('fieldset')); + // node ID. not editable. + var $label = one.lib.form.label("Node ID"); + var $input = one.lib.form.input("node id"); + $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeId); + $input.attr("disabled", true); + $input.attr("value", nodeId); + $fieldset.append($label).append($input); + // node name + var $label = one.lib.form.label("Node Name"); + var $input = one.lib.form.input("Node Name"); + $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeName); + if(switchDetails["nodeName"] != null) { + $input.attr('value', switchDetails["nodeName"]); + } + $fieldset.append($label).append($input); + // node tier + var $label = one.lib.form.label("Tier"); + var $select = one.lib.form.select.create(tiers); + $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.tier); + $select.val(switchDetails["tier"]); + $fieldset.append($label).append($select); + // operation mode + var $label = one.lib.form.label("Operation Mode"); + var $select = one.lib.form.select.create( + ["Allow reactive forwarding", "Proactive forwarding only"]); + $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.operationMode); + if ((one.main.registry != undefined) && (one.main.registry.container != 'default')) { + $select.attr("disabled", true); } + $select.val(switchDetails["mode"]); + $fieldset.append($label).append($select); + $form.append($fieldset); + return $form; + }, + popout: function($modal) { + var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.modal.datagrid, { + searchable: true, + filterable: false, + pagination: true, + flexibleRowsPerPage: true, + popout: true + }, "table-striped table-condensed"); + one.lib.modal.inject.body($modal, $gridHTML); + // attach to shown event of modal + $modal.on("shown", function() { + var url = one.f.switchmanager.rootUrl + "/nodesLearnt"; + one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) { + var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.popout(content); + $("#" + one.f.switchmanager.nodesLearnt.id.modal.datagrid).datagrid({ + dataSource: dataSource, + stretchHeight: false + }) + .on("loaded", function() { + $("#" + one.f.switchmanager.nodesLearnt.id.modal.datagrid).find("tbody span").click(function(){ + one.f.switchmanager.nodesLearnt.modal.initialize.displayPorts($(this)); + }); + }); + }); + }); + } }, - modal : { - initialize: { - updateNode: function(evt) { - one.f.switchmanager.nodesLearnt.ajax.main(one.f.switchmanager.rootUrl + "/tiers", function(tiers) { - - var nodeId = decodeURIComponent(evt.target.id); - var h3; - var footer = []; - var $body = one.f.switchmanager.nodesLearnt.modal.body.updateNode(nodeId, JSON.parse(decodeURIComponent(evt.target.getAttribute("switchDetails"))), tiers); - if (evt.target.getAttribute("privilege") == 'WRITE'){ - h3 = "Update Node Information"; - footer = one.f.switchmanager.nodesLearnt.modal.footer.updateNode(); - } else { //disable node edit - $body.find('*').attr('disabled', 'disabled'); - h3 = 'Node Information'; - } - - var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.configure, h3, "", footer); - // bind save button - $('#' + one.f.switchmanager.nodesLearnt.id.modal.save, $modal).click(function() { - one.f.switchmanager.nodesLearnt.modal.save($modal); - }); - - // inject body (nodePorts) - one.lib.modal.inject.body($modal, $body); - $modal.modal(); - }); - }, - popout: function() { - var h3 = "Nodes Learned"; - var footer = one.f.switchmanager.nodesLearnt.modal.footer.popout(); - var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.modal, h3, "", footer); - var $body = one.f.switchmanager.nodesLearnt.modal.body.popout($modal); - return $modal; - }, - displayPorts: function(ports) { - var content = JSON.parse(decodeURIComponent(ports.attr("ports"))); - - var h3 = ((ports.attr("nodeName") == "None")? ports.attr("nodeId") : ports.attr("nodeName")) - var footer = []; - var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.ports, h3, "", footer); - - var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.modal.portsDatagrid, { - searchable: true, - filterable: false, - pagination: true, - flexibleRowsPerPage: true, - popout: true - }, "table-striped table-condensed"); - one.lib.modal.inject.body($modal, $gridHTML); - $modal.on("shown", function() { - var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.displayPorts(content); - $("#" + one.f.switchmanager.nodesLearnt.id.modal.portsDatagrid).datagrid({ - dataSource: dataSource, - stretchHeight: false - }); - }); - $modal.modal(); + save: function($modal) { + var result = {}; + result['nodeName'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.nodeName, $modal).val(); + if(!one.f.switchmanager.validateName(result['nodeName'])) { + alert("Node name can contain upto 255 characters"); + return; + } + result['nodeId'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.nodeId, $modal).val(); + result['tier'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.tier, $modal).val(); + result['operationMode'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.operationMode, $modal).val(); + one.f.switchmanager.nodesLearnt.modal.ajax(result, + function(response) { + if(response.status == true) { + $modal.modal('hide'); + one.topology.update(); // refresh visual topology with new name + // TODO: Identify dashlet by inserting a nodesLearnt div + // in the dashlet() instead + one.f.switchmanager.nodesLearnt.dashlet($("#left-top .dashlet")); + } else { + alert(response.message); } + + }); + }, + ajax: function(requestData, callback) { + $.getJSON(one.f.switchmanager.rootUrl + "/nodesLearnt/update", requestData, function(response) { + callback(response); + }); + }, + footer: { + updateNode: function() { + var footer = []; + var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.nodesLearnt.id.modal.save, "btn-primary", ""); + var $saveButton = one.lib.dashlet.button.button(saveButton); + footer.push($saveButton); + + return footer; + }, + popout: function() { + // TODO: Maybe put a close button in the footer? + return []; + } + } + }, + // data functions + data : { + gridDataSource: { + abridged: function(data) { + var source = new StaticDataSource({ + columns: [ + { + property: 'nodeName', + label: 'Node Name', + sortable: true }, - body: { - updateNode: function(nodeId, switchDetails, tiers) { - var $form = $(document.createElement('form')); - var $fieldset = $(document.createElement('fieldset')); - // node ID. not editable. - var $label = one.lib.form.label("Node ID"); - var $input = one.lib.form.input("node id"); - $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeId); - $input.attr("disabled", true); - $input.attr("value", nodeId); - $fieldset.append($label).append($input); - // node name - var $label = one.lib.form.label("Node Name"); - var $input = one.lib.form.input("Node Name"); - $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeName); - if(switchDetails["nodeName"] != null) { - $input.attr('value', switchDetails["nodeName"]); - } - $fieldset.append($label).append($input); - // node tier - var $label = one.lib.form.label("Tier"); - var $select = one.lib.form.select.create(tiers); - $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.tier); - $select.val(switchDetails["tier"]); - $fieldset.append($label).append($select); - // operation mode - var $label = one.lib.form.label("Operation Mode"); - var $select = one.lib.form.select.create( - ["Allow reactive forwarding", "Proactive forwarding only"]); - $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.operationMode); - if ((one.main.registry != undefined) && (one.main.registry.container != 'default')) { - $select.attr("disabled", true); - } - $select.val(switchDetails["mode"]); - $fieldset.append($label).append($select); - $form.append($fieldset); - return $form; - }, - popout: function($modal) { - var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.modal.datagrid, { - searchable: true, - filterable: false, - pagination: true, - flexibleRowsPerPage: true, - popout: true - }, "table-striped table-condensed"); - one.lib.modal.inject.body($modal, $gridHTML); - // attach to shown event of modal - $modal.on("shown", function() { - var url = one.f.switchmanager.rootUrl + "/nodesLearnt"; - one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) { - var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.popout(content); - $("#" + one.f.switchmanager.nodesLearnt.id.modal.datagrid).datagrid({ - dataSource: dataSource, - stretchHeight: false - }) - .on("loaded", function() { - $("#" + one.f.switchmanager.nodesLearnt.id.modal.datagrid).find("tbody span").click(function(){ - one.f.switchmanager.nodesLearnt.modal.initialize.displayPorts($(this)); - }); - }); - }); - }); - } + { + property: 'nodeId', + label: 'Node ID', + sortable: true }, - save: function($modal) { - var result = {}; - result['nodeName'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.nodeName, $modal).val(); - if(!one.f.switchmanager.validateName(result['nodeName'])) { - alert("Node name can contain upto 255 characters"); - return; - } - result['nodeId'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.nodeId, $modal).val(); - result['tier'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.tier, $modal).val(); - result['operationMode'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.operationMode, $modal).val(); - one.f.switchmanager.nodesLearnt.modal.ajax(result, - function(response) { - if(response.status == true) { - $modal.modal('hide'); - one.topology.update(); // refresh visual topology with new name - // TODO: Identify dashlet by inserting a nodesLearnt div - // in the dashlet() instead - one.f.switchmanager.nodesLearnt.dashlet($("#left-top .dashlet")); - } else { - alert(response.message); - } - - }); + { + property: 'ports', + label: 'Ports', + sortable: true + } + ], + data: data.nodeData, + formatter: function(items) { + $.each(items, function (index, item) { + var nodeName = item.nodeName; + var nodeNameEntry = item.nodeName ? item.nodeName : "Click to update"; + item.nodeName = '' + nodeNameEntry + ''; + + var ports = item.ports; + var portsMatch = ports.match(/<\/span>/g); + var portsLength = 0; + if (portsMatch != null) { + portsLength = portsMatch.length; + } + item.ports = '' + portsLength +''; + }); }, - ajax: function(requestData, callback) { - $.getJSON(one.f.switchmanager.rootUrl + "/nodesLearnt/update", requestData, function(response) { - callback(response); - }); + delay: 0 + }); + return source; + + }, + popout: function(data) { + var source = new StaticDataSource({ + columns: [ + { + property: 'nodeName', + label: 'Node Name', + sortable: true }, - footer: { - updateNode: function() { - var footer = []; - var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.nodesLearnt.id.modal.save, "btn-primary", ""); - var $saveButton = one.lib.dashlet.button.button(saveButton); - footer.push($saveButton); - - return footer; - }, - popout: function() { - // TODO: Maybe put a close button in the footer? - return []; - } - } - }, - // data functions - data : { - gridDataSource: { - abridged: function(data) { - var source = new StaticDataSource({ - columns: [ - { - property: 'nodeName', - label: 'Node Name', - sortable: true - }, - { - property: 'nodeId', - label: 'Node ID', - sortable: true - }, - { - property: 'ports', - label: 'Ports', - sortable: true - } - ], - data: data.nodeData, - formatter: function(items) { - $.each(items, function (index, item) { - var nodeName = item.nodeName; - var nodeNameEntry = item.nodeName ? item.nodeName : "Click to update"; - item.nodeName = '' + nodeNameEntry + ''; - - var ports = item.ports; - var portsMatch = ports.match(/<\/span>/g); - var portsLength = 0; - if (portsMatch != null) { - portsLength = portsMatch.length; - } - item.ports = '' + portsLength +''; - }); - }, - delay: 0 - }); - return source; - - }, - popout: function(data) { - var source = new StaticDataSource({ - columns: [ - { - property: 'nodeName', - label: 'Node Name', - sortable: true - }, - { - property: 'nodeId', - label: 'Node ID', - sortable: true - }, - { - property: 'tierName', - label: 'Tier Name', - sortable: true - }, - { - property: 'mac', - label: 'MAC Address', - sortable: true - }, - { - property: 'ports', - label: 'Ports', - sortable: true - } - ], - data: data.nodeData, - formatter: function(items) { - $.each(items, function (index, item) { - var ports = item.ports; - var portsMatch = ports.match(/<\/span>/g); - var portsLength = 0; - if (portsMatch != null) { - portsLength = portsMatch.length; - } - item.ports = '' + portsLength +''; - }); - }, - delay: 0 - }); - return source; - }, - displayPorts: function(content){ - var data=[]; - var start=0;; - var finish=content.indexOf("
",start); - while(finish != -1){ - data.push({"ports":content.substring(start,finish)}); - start=finish+4 - finish=content.indexOf("
",start); - } - var source = new StaticDataSource({ - columns: [ - { - property: 'ports', - label: 'Ports', - sortable: true - } - ], - data:data, - delay: 0 - }); - - return source; - } + { + property: 'nodeId', + label: 'Node ID', + sortable: true }, - abridged : function(data) { - var result = []; - $.each(data.nodeData, function(key, value) { - var tr = {}; - var entry = []; - var nodeNameEntry = value["nodeName"] ? value["nodeName"] : "Click to update"; - - // TODO: Move anchor tag creation to one.lib.form. - var aTag; - aTag = document.createElement("a"); - aTag.privilege = data.privilege; - aTag.addEventListener("click", one.f.switchmanager.nodesLearnt.modal.initialize.updateNode); - aTag.addEventListener("mouseover", function(evt) { - evt.target.style.cursor = "pointer"; - }, false); - aTag.setAttribute("id", encodeURIComponent(value["nodeId"])); - aTag.switchDetails = value; - aTag.innerHTML = nodeNameEntry; - entry.push(aTag); - entry.push(value["nodeId"]); - entry.push(value["ports"]); - tr.entry = entry; - result.push(tr); - }); - return result; + { + property: 'tierName', + label: 'Tier Name', + sortable: true }, - popout : function(data) { - var result = []; - $.each(data.nodeData, function(key, value) { - var tr = {}; - // fill up all the td's - var entry = []; - var nodenameentry = value["nodeName"] ? value["nodeName"] : "No name provided"; - entry.push(nodenameentry); - entry.push(value["nodeId"]); - entry.push(value["tierName"]); - entry.push(value["mac"]); - entry.push(value["ports"]); - tr.entry = entry; - result.push(tr); - }); - return result; + { + property: 'mac', + label: 'MAC Address', + sortable: true + }, + { + property: 'ports', + label: 'Ports', + sortable: true } + ], + data: data.nodeData, + formatter: function(items) { + $.each(items, function (index, item) { + var ports = item.ports; + var portsMatch = ports.match(/<\/span>/g); + var portsLength = 0; + if (portsMatch != null) { + portsLength = portsMatch.length; + } + item.ports = '' + portsLength +''; + }); + }, + delay: 0 + }); + return source; + }, + displayPorts: function(content){ + var data=[]; + var start=0;; + var finish=content.indexOf("
",start); + while(finish != -1){ + data.push({"ports":content.substring(start,finish)}); + start=finish+4 + finish=content.indexOf("
",start); + } + var source = new StaticDataSource({ + columns: [ + { + property: 'ports', + label: 'Ports', + sortable: true + } + ], + data:data, + delay: 0 + }); + + return source; + } + }, + abridged : function(data) { + var result = []; + $.each(data.nodeData, function(key, value) { + var tr = {}; + var entry = []; + var nodeNameEntry = value["nodeName"] ? value["nodeName"] : "Click to update"; + + // TODO: Move anchor tag creation to one.lib.form. + var aTag; + aTag = document.createElement("a"); + aTag.privilege = data.privilege; + aTag.addEventListener("click", one.f.switchmanager.nodesLearnt.modal.initialize.updateNode); + aTag.addEventListener("mouseover", function(evt) { + evt.target.style.cursor = "pointer"; + }, false); + aTag.setAttribute("id", encodeURIComponent(value["nodeId"])); + aTag.switchDetails = value; + aTag.innerHTML = nodeNameEntry; + entry.push(aTag); + entry.push(value["nodeId"]); + entry.push(value["ports"]); + tr.entry = entry; + result.push(tr); + }); + return result; + }, + popout : function(data) { + var result = []; + $.each(data.nodeData, function(key, value) { + var tr = {}; + // fill up all the td's + var entry = []; + var nodenameentry = value["nodeName"] ? value["nodeName"] : "No name provided"; + entry.push(nodenameentry); + entry.push(value["nodeId"]); + entry.push(value["tierName"]); + entry.push(value["mac"]); + entry.push(value["ports"]); + tr.entry = entry; + result.push(tr); + }); + return result; } + } }; one.f.switchmanager.subnetGatewayConfig = { - id: { - dashlet: { - addIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addIP", - addPorts: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addPorts", - removeIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_removeIP", - datagrid: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_datagrid", - selectAll: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_selectAll" - }, - modal: { - modal: "one_f_switchmanager_subnetGatewayConfig_id_modal_modal", - ports : "one_f_switchmanager_subnetGatewayConfig_id_modal_ports", - save: "one_f_switchmanager_subnetGatewayConfig_id_modal_save", - remove: "one_f_switchmanager_subnetGatewayConfig_id_modal_remove", - cancel: "one_f_switchmanager_subnetGatewayConfig_id_modal_cancel", - form: { - name : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayname", - gatewayIPAddress : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayipaddress", - nodeId: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_nodeid", - ports: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_ports" - } + id: { + dashlet: { + addIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addIP", + addPorts: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addPorts", + removeIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_removeIP", + datagrid: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_datagrid", + selectAll: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_selectAll" + }, + modal: { + modal: "one_f_switchmanager_subnetGatewayConfig_id_modal_modal", + ports : "one_f_switchmanager_subnetGatewayConfig_id_modal_ports", + save: "one_f_switchmanager_subnetGatewayConfig_id_modal_save", + remove: "one_f_switchmanager_subnetGatewayConfig_id_modal_remove", + cancel: "one_f_switchmanager_subnetGatewayConfig_id_modal_cancel", + form: { + name : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayname", + gatewayIPAddress : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayipaddress", + nodeId: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_nodeid", + ports: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_ports" + } + } + }, + // device ajax calls + dashlet: function($dashlet) { + one.lib.dashlet.empty($dashlet); + $dashlet.append(one.lib.dashlet.header(one.f.dashlet.subnetGatewayConfig.name)); + // Add gateway IP Address button + var url = one.f.switchmanager.rootUrl + "/subnets"; + one.f.switchmanager.subnetGatewayConfig.ajax.main(url, {}, function(content) { + + if (content.privilege === 'WRITE') { + var button = one.lib.dashlet.button.single("Add Gateway IP Address", + one.f.switchmanager.subnetGatewayConfig.id.dashlet.addIPAddress, "btn-primary", "btn-mini"); + var $button = one.lib.dashlet.button.button(button); + $button.click(function() { + var $modal = one.f.switchmanager.subnetGatewayConfig.modal.initialize.gateway(); + $modal.modal(); + }); + $dashlet.append($button); + + // Delete gateway ip address button + var button = one.lib.dashlet.button.single("Remove Gateway IP Address", + one.f.switchmanager.subnetGatewayConfig.id.dashlet.removeIPAddress, "btn-danger", "btn-mini"); + var $button = one.lib.dashlet.button.button(button); + $button.click(function() { + var gatewaysToDelete = []; + var checkedCheckBoxes = $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).find("tbody input:checked") + checkedCheckBoxes.each(function(index, value) { + gatewaysToDelete.push(checkedCheckBoxes[index].id); + }); + if (checkedCheckBoxes.size() === 0) { + return false; } - }, - // device ajax calls - dashlet: function($dashlet) { - one.lib.dashlet.empty($dashlet); - $dashlet.append(one.lib.dashlet.header(one.f.dashlet.subnetGatewayConfig.name)); - // Add gateway IP Address button - var url = one.f.switchmanager.rootUrl + "/subnets"; - one.f.switchmanager.subnetGatewayConfig.ajax.main(url, {}, function(content) { - - if (content.privilege === 'WRITE') { - var button = one.lib.dashlet.button.single("Add Gateway IP Address", - one.f.switchmanager.subnetGatewayConfig.id.dashlet.addIPAddress, "btn-primary", "btn-mini"); - var $button = one.lib.dashlet.button.button(button); - $button.click(function() { - var $modal = one.f.switchmanager.subnetGatewayConfig.modal.initialize.gateway(); - $modal.modal(); - }); - $dashlet.append($button); - - // Delete gateway ip address button - var button = one.lib.dashlet.button.single("Remove Gateway IP Address", - one.f.switchmanager.subnetGatewayConfig.id.dashlet.removeIPAddress, "btn-danger", "btn-mini"); - var $button = one.lib.dashlet.button.button(button); - $button.click(function() { - var gatewaysToDelete = []; - var checkedCheckBoxes = $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).find("tbody input:checked") - checkedCheckBoxes.each(function(index, value) { - gatewaysToDelete.push(checkedCheckBoxes[index].id); - }); - if (checkedCheckBoxes.size() === 0) { - return false; - } - one.f.switchmanager.subnetGatewayConfig.modal.removeMultiple.dialog(gatewaysToDelete) - }); - $dashlet.append($button); - - // Add Ports button - var button = one.lib.dashlet.button.single("Add Ports", - one.f.switchmanager.subnetGatewayConfig.id.dashlet.addPorts, "btn-primary", "btn-mini"); - var $button = one.lib.dashlet.button.button(button); - $button.click(function() { - if (one.f.switchmanager.subnetGatewayConfig.registry.gateways.length === 0) { - alert('No Gateways Exist'); - return false; - } - var $modal = one.f.switchmanager.subnetGatewayConfig.modal.initialize.ports(); - $modal.modal(); - }); - $dashlet.append($button); + one.f.switchmanager.subnetGatewayConfig.modal.removeMultiple.dialog(gatewaysToDelete) + }); + $dashlet.append($button); + + // Add Ports button + var button = one.lib.dashlet.button.single("Add Ports", + one.f.switchmanager.subnetGatewayConfig.id.dashlet.addPorts, "btn-primary", "btn-mini"); + var $button = one.lib.dashlet.button.button(button); + $button.click(function() { + if (one.f.switchmanager.subnetGatewayConfig.registry.gateways.length === 0) { + alert('No Gateways Exist'); + return false; + } + var $modal = one.f.switchmanager.subnetGatewayConfig.modal.initialize.ports(); + $modal.modal(); + }); + $dashlet.append($button); + } + var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid, { + searchable: true, + filterable: false, + pagination: true, + flexibleRowsPerPage: true + }, "table-striped table-condensed"); + $dashlet.append($gridHTML); + var dataSource = one.f.switchmanager.subnetGatewayConfig.data.devicesgrid(content); + $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource}) + .on("loaded", function() { + $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll).click(function() { + $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).find(':checkbox').prop('checked', + $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll).is(':checked')); + }); + $(".subnetGatewayConfig").click(function(e){ + if (!$('.subnetGatewayConfig[type=checkbox]:not(:checked)').length) { + $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll) + .prop("checked", + true); + } else { + $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll) + .prop("checked", + false); } - var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid, { - searchable: true, - filterable: false, - pagination: true, - flexibleRowsPerPage: true - }, "table-striped table-condensed"); - $dashlet.append($gridHTML); - var dataSource = one.f.switchmanager.subnetGatewayConfig.data.devicesgrid(content); - $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource}) - .on("loaded", function() { - $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll).click(function() { - $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).find(':checkbox').prop('checked', - $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll).is(':checked')); - }); - $(".subnetGatewayConfig").click(function(e){ - if (!$('.subnetGatewayConfig[type=checkbox]:not(:checked)').length) { - $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll) - .prop("checked", - true); - } else { - $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll) - .prop("checked", - false); - } - e.stopPropagation(); - }); - }); + e.stopPropagation(); + }); }); + }); + }, + ajax : { + main : function(url, requestData, callback) { + $.getJSON(url, requestData, function(data) { + callback(data); + }); + } + }, + registry: {}, + modal : { + initialize: { + gateway: function() { + var h3 = "Add Gateway IP Address"; + var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer(); + var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, "", footer); + // bind save button + $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() { + one.f.switchmanager.subnetGatewayConfig.modal.save.gateway($modal); + }); + var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.gateway(); + one.lib.modal.inject.body($modal, $body); + return $modal; + }, + ports: function() { + var h3 = "Add Ports"; + var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer(); + var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.ports, h3, "", footer); + // bind save button + $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() { + one.f.switchmanager.subnetGatewayConfig.modal.save.ports($modal); + }); + + // TODO: Change to subnetGateway instead. + one.f.switchmanager.spanPortConfig.modal.ajax.nodes(function(nodes, nodeports) { + var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.ports(nodes, nodeports); + one.lib.modal.inject.body($modal, $body); + }); + return $modal; + } }, - ajax : { - main : function(url, requestData, callback) { - $.getJSON(url, requestData, function(data) { - callback(data); + save: { + gateway: function($modal) { + var result = {}; + result['gatewayName'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val(); + if(!one.f.switchmanager.validateName(result['gatewayName'])) { + alert("Gateway name can contain upto 255 characters"); + return; + } + result['gatewayIPAddress'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress, $modal).val(); + one.f.switchmanager.subnetGatewayConfig.modal.ajax.gateway(result, + function(response) { + if(response.status == true) { + $modal.modal('hide'); + one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); + } else { + alert(response.message); + } }); + }, + ports: function($modal) { + var result = {}; + var gatewayRegistryIndex = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val(); + result['portsName'] = one.f.switchmanager.subnetGatewayConfig.registry.gateways[gatewayRegistryIndex]; + result['nodeId'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId, $modal).val(); + result['ports'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports, $modal).val(); + if(!result['portsName'] || result['portsName'] == "") { + alert("No gateway chosen. Cannot add port"); + return; } - }, - registry: {}, - modal : { - initialize: { - gateway: function() { - var h3 = "Add Gateway IP Address"; - var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer(); - var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, "", footer); - // bind save button - $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() { - one.f.switchmanager.subnetGatewayConfig.modal.save.gateway($modal); - }); - var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.gateway(); - one.lib.modal.inject.body($modal, $body); - return $modal; - }, - ports: function() { - var h3 = "Add Ports"; - var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer(); - var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.ports, h3, "", footer); - // bind save button - $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() { - one.f.switchmanager.subnetGatewayConfig.modal.save.ports($modal); - }); - - // TODO: Change to subnetGateway instead. - one.f.switchmanager.spanPortConfig.modal.ajax.nodes(function(nodes, nodeports) { - var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.ports(nodes, nodeports); - one.lib.modal.inject.body($modal, $body); - }); - return $modal; - } - }, - save: { - gateway: function($modal) { - var result = {}; - result['gatewayName'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val(); - if(!one.f.switchmanager.validateName(result['gatewayName'])) { - alert("Gateway name can contain upto 255 characters"); - return; - } - result['gatewayIPAddress'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress, $modal).val(); - one.f.switchmanager.subnetGatewayConfig.modal.ajax.gateway(result, - function(response) { - if(response.status == true) { - $modal.modal('hide'); - one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); - } else { - alert(response.message); - } - }); - }, - ports: function($modal) { - var result = {}; - var gatewayRegistryIndex = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val(); - result['portsName'] = one.f.switchmanager.subnetGatewayConfig.registry.gateways[gatewayRegistryIndex]; - result['nodeId'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId, $modal).val(); - result['ports'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports, $modal).val(); - if(!result['portsName'] || result['portsName'] == "") { - alert("No gateway chosen. Cannot add port"); - return; - } - if(!result['nodeId'] || result['nodeId'] == "") { - alert("Please select a node."); - return; - } - if(!result['ports'] || result['ports'] == "") { - alert("Please choose a port."); - return; - } - one.f.switchmanager.subnetGatewayConfig.modal.ajax.ports(result, - function(response) { - if(response.status == true) { - $modal.modal('hide'); - one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); - } else { - alert(response.message); - } - }); - } - }, - body: { - gateway: function() { - var $form = $(document.createElement('form')); - var $fieldset = $(document.createElement('fieldset')); - // gateway name - var $label = one.lib.form.label("Name"); - var $input = one.lib.form.input("Name"); - $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name); - $fieldset.append($label).append($input); - // gateway IP Mask - var $label = one.lib.form.label("Gateway IP Address/Mask"); - var $input = one.lib.form.input("Gateway IP Address/Mask"); - var $help = one.lib.form.help('Example: 192.168.10.254/16'); - $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress); - $fieldset.append($label).append($input).append($help); - - $form.append($fieldset); - return $form; - }, - ports: function(nodes, nodeports) { - var $form = $(document.createElement('form')); - var $fieldset = $(document.createElement('fieldset')); - // gateways drop down - var $label = one.lib.form.label("Gateway Name"); - var $select = one.lib.form.select.create(one.f.switchmanager.subnetGatewayConfig.registry.gateways); - $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name); - one.lib.form.select.prepend($select, { '' : 'Please Select a Gateway' }); - $select.val($select.find("option:first").val()); - $fieldset.append($label).append($select); - - // node ID - var $label = one.lib.form.label("Node ID"); - var $select = one.lib.form.select.create(nodes); - $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId); - one.lib.form.select.prepend($select, { '' : 'Please Select a Node' }); - $select.val($select.find("option:first").val()); - $fieldset.append($label).append($select); - - // bind onchange - $select.change(function() { - // retrieve port value - var node = $(this).find('option:selected').attr('value'); - one.f.switchmanager.subnetGatewayConfig.registry['currentNode'] = node; - var $ports = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports); - var ports = nodeports[node]; - var options = {}; - $(ports).each(function(idx, val) { - options[val.internalPortName] = val.portName+' ('+val.portId+')'; - }); - one.lib.form.select.inject($ports, options); - one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' }); - $ports.val($ports.find("option:first").val()); - }); - - // ports - var $label = one.lib.form.label("Select Port"); - var $select = one.lib.form.select.create(); - one.lib.form.select.prepend($select, { '' : 'Please Select a Port' }); - $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports); - $fieldset.append($label).append($select); - - $form.append($fieldset); - return $form; - } - }, - ajax: { - gateway: function(requestData, callback) { - $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/add", requestData, function(data) { - callback(data); + if(!result['nodeId'] || result['nodeId'] == "") { + alert("Please select a node."); + return; + } + if(!result['ports'] || result['ports'] == "") { + alert("Please choose a port."); + return; + } + one.f.switchmanager.subnetGatewayConfig.modal.ajax.ports(result, + function(response) { + if(response.status == true) { + $modal.modal('hide'); + one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); + } else { + alert(response.message); + } }); - }, - ports: function(requestData, callback) { - $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/ports/add", requestData, function(data) { - callback(data); + } + }, + body: { + gateway: function() { + var $form = $(document.createElement('form')); + var $fieldset = $(document.createElement('fieldset')); + // gateway name + var $label = one.lib.form.label("Name"); + var $input = one.lib.form.input("Name"); + $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name); + $fieldset.append($label).append($input); + // gateway IP Mask + var $label = one.lib.form.label("Gateway IP Address/Mask"); + var $input = one.lib.form.input("Gateway IP Address/Mask"); + var $help = one.lib.form.help('Example: 192.168.10.254/16'); + $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress); + $fieldset.append($label).append($input).append($help); + + $form.append($fieldset); + return $form; + }, + ports: function(nodes, nodeports) { + var $form = $(document.createElement('form')); + var $fieldset = $(document.createElement('fieldset')); + // gateways drop down + var $label = one.lib.form.label("Gateway Name"); + var $select = one.lib.form.select.create(one.f.switchmanager.subnetGatewayConfig.registry.gateways); + $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name); + one.lib.form.select.prepend($select, { '' : 'Please Select a Gateway' }); + $select.val($select.find("option:first").val()); + $fieldset.append($label).append($select); + + // node ID + var $label = one.lib.form.label("Node ID"); + var $select = one.lib.form.select.create(nodes); + $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId); + one.lib.form.select.prepend($select, { '' : 'Please Select a Node' }); + $select.val($select.find("option:first").val()); + $fieldset.append($label).append($select); + + // bind onchange + $select.change(function() { + // retrieve port value + var node = $(this).find('option:selected').attr('value'); + one.f.switchmanager.subnetGatewayConfig.registry['currentNode'] = node; + var $ports = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports); + var ports = nodeports[node]; + var options = {}; + $(ports).each(function(idx, val) { + options[val.internalPortName] = val.portName+' ('+val.portId+')'; + }); + one.lib.form.select.inject($ports, options); + one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' }); + $ports.val($ports.find("option:first").val()); }); - } - }, - footer : function() { - var footer = []; - var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.subnetGatewayConfig.id.modal.save, "btn-primary", ""); - var $saveButton = one.lib.dashlet.button.button(saveButton); - footer.push($saveButton); - return footer; - }, - removeMultiple: { - dialog: function(gatewaysToDelete) { - var h3 = 'Remove Gateway IP Address'; - - var footer = one.f.switchmanager.subnetGatewayConfig.modal.removeMultiple.footer(); - var $body = one.f.switchmanager.subnetGatewayConfig.modal.removeMultiple.body(gatewaysToDelete); - var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, $body, footer); - - // bind close button - $('#'+one.f.switchmanager.subnetGatewayConfig.id.modal.cancel, $modal).click(function() { - $modal.modal('hide'); - }); - - // bind remove rule button - $('#'+one.f.switchmanager.subnetGatewayConfig.id.modal.remove, $modal).click(this, function(e) { - var requestData = {}; - if (gatewaysToDelete.length > 0) { - requestData["gatewaysToDelete"] = gatewaysToDelete.toString(); - var url = one.f.switchmanager.rootUrl + "/subnetGateway/delete"; - one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) { - $modal.modal('hide'); - if (response.status == true) { - // refresh dashlet by passing dashlet div as param - one.lib.alert("Gateway IP Address(es) successfully removed"); - } else { - alert(response.message); - } - one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); - }); - } - }); - $modal.modal(); - }, - footer : function() { - var footer = []; - var remove = one.lib.dashlet.button.single('Remove Gateway IP Address',one.f.switchmanager.subnetGatewayConfig.id.modal.remove, 'btn-danger', ''); - var $remove = one.lib.dashlet.button.button(remove); - footer.push($remove); - - var cancel = one.lib.dashlet.button.single('Cancel', one.f.switchmanager.subnetGatewayConfig.id.modal.cancel, '', ''); - var $cancel = one.lib.dashlet.button.button(cancel); - footer.push($cancel); - - return footer; - }, - body : function (gatewayList) { - var $p = $(document.createElement('p')); - var p = 'Remove the following Gateway IP Address(es)?'; - //creata a BS label for each rule and append to list - $(gatewayList).each(function(){ - var $span = $(document.createElement('span')); - $span.append(this); - p += '
' + $span[0].outerHTML; - }); - $p.append(p); - return $p; - } - } + + // ports + var $label = one.lib.form.label("Select Port"); + var $select = one.lib.form.select.create(); + one.lib.form.select.prepend($select, { '' : 'Please Select a Port' }); + $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports); + $fieldset.append($label).append($select); + + $form.append($fieldset); + return $form; + } }, - // data functions - data : { - devicesgrid: function(data) { - one.f.switchmanager.subnetGatewayConfig.registry.gateways = []; - var source = new StaticDataSource({ - columns: [ - { - property: 'selector', - label: "", - sortable: false - }, - { - property: 'name', - label: 'Name', - sortable: true - }, - { - property: 'subnet', - label: 'Gateway IP Address/Mask', - sortable: true - }, - { - property: 'nodePorts', - label: 'Ports', - sortable: false - } - ], - data: data.nodeData, - formatter: function(items) { - $.each(items, function(index, tableRow) { - tableRow["selector"] = ''; - var json = tableRow["nodePorts"]; - var nodePorts = JSON.parse(json); - var nodePortHtml = "

"; - $.each(nodePorts, function(index, nodePort) { - nodePortHtml += nodePort["nodePortName"] + " @ " + nodePort["nodeName"]; - nodePortHtml += " "; - nodePortHtml += 'Remove'; - nodePortHtml += "
"; - }); - nodePortHtml += "
"; - tableRow["nodePorts"] = nodePortHtml; - }); - - }, - delay: 0 - }); - // populate the registry with subnet names - one.f.switchmanager.subnetGatewayConfig.registry.gateways = []; - $.each(data.nodeData, function(key, value) { - one.f.switchmanager.subnetGatewayConfig.registry.gateways.push(value["name"]); - }); - return source; - }, - devices : function(data) { - var result = []; - one.f.switchmanager.subnetGatewayConfig.registry.gateways = []; - $.each(data.nodeData, function(key, value) { - var tr = {}; - // fill up all the td's - var subnetConfigObject = $.parseJSON(value["json"]); - var nodePorts = subnetConfigObject.nodePorts; - var $nodePortsContainer = $(document.createElement("div")); - - for(var i = 0; i < nodePorts.length; i++) { - var nodePort = nodePorts[i]; - $nodePortsContainer.append(nodePort + " "); - // add delete anchor tag to delete ports - var aTag = document.createElement("a"); - aTag.setAttribute("id", encodeURIComponent(nodePort)); - aTag.gatewayName = value["name"]; - aTag.addEventListener("click", function(evt) { - var htmlPortAnchor = evt.target; - var requestData = {}; - requestData["gatewayName"] = evt.target.gatewayName; - requestData["nodePort"] = decodeURIComponent(evt.target.id); - // make ajax call to delete port - var url = one.f.switchmanager.rootUrl + "/subnetGateway/ports/delete"; - one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) { - if(response.status == true) { - // refresh dashlet by passing dashlet div as param - one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); - } else { - alert(response.message); - } - }); - - }); - aTag.addEventListener("mouseover", function(evt) { - evt.target.style.cursor = "pointer"; - }, false); - aTag.innerHTML = "Remove"; - $nodePortsContainer.append(aTag); - $nodePortsContainer.append("
"); - } - - // store gateways in the registry so that they can be used in the add ports popup - one.f.switchmanager.subnetGatewayConfig.registry.gateways.push(value["name"]); - var entry = []; - var checkbox = document.createElement("input"); - checkbox.setAttribute("type", "checkbox"); - checkbox.setAttribute("id", value["name"]); - entry.push(checkbox); - entry.push(value["name"]); - entry.push(value["subnet"]); - entry.push($nodePortsContainer); - tr.entry = entry; - result.push(tr); + ajax: { + gateway: function(requestData, callback) { + $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/add", requestData, function(data) { + callback(data); + }); + }, + ports: function(requestData, callback) { + $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/ports/add", requestData, function(data) { + callback(data); + }); + } + }, + footer : function() { + var footer = []; + var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.subnetGatewayConfig.id.modal.save, "btn-primary", ""); + var $saveButton = one.lib.dashlet.button.button(saveButton); + footer.push($saveButton); + return footer; + }, + removeMultiple: { + dialog: function(gatewaysToDelete) { + var h3 = 'Remove Gateway IP Address'; + + var footer = one.f.switchmanager.subnetGatewayConfig.modal.removeMultiple.footer(); + var $body = one.f.switchmanager.subnetGatewayConfig.modal.removeMultiple.body(gatewaysToDelete); + var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, $body, footer); + + // bind close button + $('#'+one.f.switchmanager.subnetGatewayConfig.id.modal.cancel, $modal).click(function() { + $modal.modal('hide'); + }); + + // bind remove rule button + $('#'+one.f.switchmanager.subnetGatewayConfig.id.modal.remove, $modal).click(this, function(e) { + var requestData = {}; + if (gatewaysToDelete.length > 0) { + requestData["gatewaysToDelete"] = gatewaysToDelete.toString(); + var url = one.f.switchmanager.rootUrl + "/subnetGateway/delete"; + one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) { + $modal.modal('hide'); + if (response.status == true) { + // refresh dashlet by passing dashlet div as param + one.lib.alert("Gateway IP Address(es) successfully removed"); + } else { + alert(response.message); + } + one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); }); - return result; - } + } + }); + $modal.modal(); + }, + footer : function() { + var footer = []; + var remove = one.lib.dashlet.button.single('Remove Gateway IP Address',one.f.switchmanager.subnetGatewayConfig.id.modal.remove, 'btn-danger', ''); + var $remove = one.lib.dashlet.button.button(remove); + footer.push($remove); + + var cancel = one.lib.dashlet.button.single('Cancel', one.f.switchmanager.subnetGatewayConfig.id.modal.cancel, '', ''); + var $cancel = one.lib.dashlet.button.button(cancel); + footer.push($cancel); + + return footer; + }, + body : function (gatewayList) { + var $p = $(document.createElement('p')); + var p = 'Remove the following Gateway IP Address(es)?'; + //creata a BS label for each rule and append to list + $(gatewayList).each(function(){ + var $span = $(document.createElement('span')); + $span.append(this); + p += '
' + $span[0].outerHTML; + }); + $p.append(p); + return $p; + } + } + }, + // data functions + data : { + devicesgrid: function(data) { + one.f.switchmanager.subnetGatewayConfig.registry.gateways = []; + var source = new StaticDataSource({ + columns: [ + { + property: 'selector', + label: "", + sortable: false + }, + { + property: 'name', + label: 'Name', + sortable: true + }, + { + property: 'subnet', + label: 'Gateway IP Address/Mask', + sortable: true + }, + { + property: 'nodePorts', + label: 'Ports', + sortable: false + } + ], + data: data.nodeData, + formatter: function(items) { + $.each(items, function(index, tableRow) { + tableRow["selector"] = ''; + var json = tableRow["nodePorts"]; + var nodePorts = JSON.parse(json); + var nodePortHtml = "
"; + $.each(nodePorts, function(index, nodePort) { + nodePortHtml += nodePort["nodePortName"] + " @ " + nodePort["nodeName"]; + nodePortHtml += " "; + nodePortHtml += 'Remove'; + nodePortHtml += "
"; + }); + nodePortHtml += "
"; + tableRow["nodePorts"] = nodePortHtml; + }); + + }, + delay: 0 + }); + // populate the registry with subnet names + one.f.switchmanager.subnetGatewayConfig.registry.gateways = []; + $.each(data.nodeData, function(key, value) { + one.f.switchmanager.subnetGatewayConfig.registry.gateways.push(value["name"]); + }); + return source; }, - actions: { - deleteNodePort: function(htmlPortAnchor) { + devices : function(data) { + var result = []; + one.f.switchmanager.subnetGatewayConfig.registry.gateways = []; + $.each(data.nodeData, function(key, value) { + var tr = {}; + // fill up all the td's + var subnetConfigObject = $.parseJSON(value["json"]); + var nodePorts = subnetConfigObject.nodePorts; + var $nodePortsContainer = $(document.createElement("div")); + + for(var i = 0; i < nodePorts.length; i++) { + var nodePort = nodePorts[i]; + $nodePortsContainer.append(nodePort + " "); + // add delete anchor tag to delete ports + var aTag = document.createElement("a"); + aTag.setAttribute("id", encodeURIComponent(nodePort)); + aTag.gatewayName = value["name"]; + aTag.addEventListener("click", function(evt) { + var htmlPortAnchor = evt.target; var requestData = {}; - requestData["gatewayName"] = htmlPortAnchor.getAttribute("gatewayName"); - requestData["nodePort"] = decodeURIComponent(htmlPortAnchor.id); + requestData["gatewayName"] = evt.target.gatewayName; + requestData["nodePort"] = decodeURIComponent(evt.target.id); // make ajax call to delete port var url = one.f.switchmanager.rootUrl + "/subnetGateway/ports/delete"; one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) { - if(response.status == true) { - // refresh dashlet by passing dashlet div as param - one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); - } else { - alert(response.message); - } + if(response.status == true) { + // refresh dashlet by passing dashlet div as param + one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); + } else { + alert(response.message); + } }); + + }); + aTag.addEventListener("mouseover", function(evt) { + evt.target.style.cursor = "pointer"; + }, false); + aTag.innerHTML = "Remove"; + $nodePortsContainer.append(aTag); + $nodePortsContainer.append("
"); + } + + // store gateways in the registry so that they can be used in the add ports popup + one.f.switchmanager.subnetGatewayConfig.registry.gateways.push(value["name"]); + var entry = []; + var checkbox = document.createElement("input"); + checkbox.setAttribute("type", "checkbox"); + checkbox.setAttribute("id", value["name"]); + entry.push(checkbox); + entry.push(value["name"]); + entry.push(value["subnet"]); + entry.push($nodePortsContainer); + tr.entry = entry; + result.push(tr); + }); + return result; + } + }, + actions: { + deleteNodePort: function(htmlPortAnchor) { + var requestData = {}; + requestData["gatewayName"] = htmlPortAnchor.getAttribute("gatewayName"); + requestData["nodePort"] = decodeURIComponent(htmlPortAnchor.id); + // make ajax call to delete port + var url = one.f.switchmanager.rootUrl + "/subnetGateway/ports/delete"; + one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) { + if(response.status == true) { + // refresh dashlet by passing dashlet div as param + one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet")); + } else { + alert(response.message); } + }); } + } } one.f.switchmanager.staticRouteConfig = { - id: { - dashlet: { - add: "one_f_switchmanager_staticRouteConfig_id_dashlet_add", - remove: "one_f_switchmanager_staticRouteConfig_id_dashlet_remove", - datagrid: "one_f_switchmanager_staticRouteConfig_id_dashlet_datagrid", - selectAll: "one_f_switchmanager_staticRouteConfig_id_dashlet_selectAll" - }, - modal: { - modal: "one_f_switchmanager_staticRouteConfig_id_modal_modal", - save: "one_f_switchmanager_staticRouteConfig_id_modal_save", - cancel: "one_f_switchmanager_staticRouteConfig_id_modal_cancel", - remove: "one_f_switchmanager_staticRouteConfig_id_modal_remove", - form: { - routeName : "one_f_switchmanager_staticRouteConfig_id_modal_form_routename", - staticRoute : "one_f_switchmanager_staticRouteConfig_id_modal_form_staticroute", - nextHop : "one_f_switchmanager_staticRouteConfig_id_modal_form_nexthop", + id: { + dashlet: { + add: "one_f_switchmanager_staticRouteConfig_id_dashlet_add", + remove: "one_f_switchmanager_staticRouteConfig_id_dashlet_remove", + datagrid: "one_f_switchmanager_staticRouteConfig_id_dashlet_datagrid", + selectAll: "one_f_switchmanager_staticRouteConfig_id_dashlet_selectAll" + }, + modal: { + modal: "one_f_switchmanager_staticRouteConfig_id_modal_modal", + save: "one_f_switchmanager_staticRouteConfig_id_modal_save", + cancel: "one_f_switchmanager_staticRouteConfig_id_modal_cancel", + remove: "one_f_switchmanager_staticRouteConfig_id_modal_remove", + form: { + routeName : "one_f_switchmanager_staticRouteConfig_id_modal_form_routename", + staticRoute : "one_f_switchmanager_staticRouteConfig_id_modal_form_staticroute", + nextHop : "one_f_switchmanager_staticRouteConfig_id_modal_form_nexthop", + } + } + }, + dashlet: function($dashlet) { + one.lib.dashlet.empty($dashlet); + var url = one.f.switchmanager.rootUrl + "/staticRoutes"; + one.f.switchmanager.staticRouteConfig.ajax.main(url, {}, function(content) { + + if (content.privilege === 'WRITE') { + // Add static route button + var button = one.lib.dashlet.button.single("Add Static Route", one.f.switchmanager.staticRouteConfig.id.dashlet.add, "btn-primary", "btn-mini"); + var $button = one.lib.dashlet.button.button(button); + $button.click(function() { + var $modal = one.f.switchmanager.staticRouteConfig.modal.initialize(); + $modal.modal(); + }); + $dashlet.append(one.lib.dashlet.header(one.f.dashlet.staticRouteConfig.name)); + $dashlet.append($button); + + // Delete static route button + var button = one.lib.dashlet.button.single("Remove Static Route", one.f.switchmanager.staticRouteConfig.id.dashlet.remove, "btn-danger", "btn-mini"); + var $button = one.lib.dashlet.button.button(button); + $button.click(function() { + var routesToDelete = []; + var checkedCheckBoxes = $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).find("tbody input:checked"); + checkedCheckBoxes.each(function(index, value) { + routesToDelete.push(checkedCheckBoxes[index].id); + }); + if (checkedCheckBoxes.size() === 0) { + return false; + } + one.f.switchmanager.staticRouteConfig.modal.removeMultiple.dialog(routesToDelete); + }); + $dashlet.append($button); + } + var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid, { + searchable: true, + filterable: false, + pagination: true, + flexibleRowsPerPage: true + }, "table-striped table-condensed"); + $dashlet.append($gridHTML); + var dataSource = one.f.switchmanager.staticRouteConfig.data.staticRouteConfigGrid(content); + $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource}) + .on("loaded", function() { + $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll).click(function() { + $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).find(':checkbox').prop('checked', + $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll).is(':checked')); + }); + $(".staticRoute").click(function(e){ + if (!$('.staticRoute[type=checkbox]:not(:checked)').length) { + $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll) + .prop("checked", + true); + } else { + $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll) + .prop("checked", + false); } + e.stopPropagation(); + }); + }); + }); + }, + // device ajax calls + ajax : { + main : function(url, requestData, callback) { + $.getJSON(url, requestData, function(data) { + callback(data); + }); + } + }, + registry: {}, + modal : { + initialize: function() { + var h3 = "Add Static Route"; + var footer = one.f.switchmanager.staticRouteConfig.modal.footer(); + var $modal = one.lib.modal.spawn(one.f.switchmanager.staticRouteConfig.id.modal.modal, h3, "", footer); + // bind save button + $('#' + one.f.switchmanager.staticRouteConfig.id.modal.save, $modal).click(function() { + one.f.switchmanager.staticRouteConfig.modal.save($modal); + }); + var $body = one.f.switchmanager.staticRouteConfig.modal.body(); + one.lib.modal.inject.body($modal, $body); + return $modal; + }, + save: function($modal) { + var result = {}; + result['routeName'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.routeName, $modal).val(); + result['staticRoute'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.staticRoute, $modal).val(); + result['nextHop'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.nextHop, $modal).val(); + one.f.switchmanager.staticRouteConfig.modal.ajax.staticRouteConfig(result, function(response) { + if(response.status == true) { + $modal.modal('hide'); + // refresh dashlet by passing dashlet div as param + one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet")); + } else { + // TODO: Show error message in a error message label instead. + alert(response.message); } + }); }, - dashlet: function($dashlet) { - one.lib.dashlet.empty($dashlet); - var url = one.f.switchmanager.rootUrl + "/staticRoutes"; - one.f.switchmanager.staticRouteConfig.ajax.main(url, {}, function(content) { - - if (content.privilege === 'WRITE') { - // Add static route button - var button = one.lib.dashlet.button.single("Add Static Route", one.f.switchmanager.staticRouteConfig.id.dashlet.add, "btn-primary", "btn-mini"); - var $button = one.lib.dashlet.button.button(button); - $button.click(function() { - var $modal = one.f.switchmanager.staticRouteConfig.modal.initialize(); - $modal.modal(); - }); - $dashlet.append(one.lib.dashlet.header(one.f.dashlet.staticRouteConfig.name)); - $dashlet.append($button); - - // Delete static route button - var button = one.lib.dashlet.button.single("Remove Static Route", one.f.switchmanager.staticRouteConfig.id.dashlet.remove, "btn-danger", "btn-mini"); - var $button = one.lib.dashlet.button.button(button); - $button.click(function() { - var routesToDelete = []; - var checkedCheckBoxes = $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).find("tbody input:checked"); - checkedCheckBoxes.each(function(index, value) { - routesToDelete.push(checkedCheckBoxes[index].id); - }); - if (checkedCheckBoxes.size() === 0) { - return false; - } - one.f.switchmanager.staticRouteConfig.modal.removeMultiple.dialog(routesToDelete); - }); - $dashlet.append($button); - } - var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid, { - searchable: true, - filterable: false, - pagination: true, - flexibleRowsPerPage: true - }, "table-striped table-condensed"); - $dashlet.append($gridHTML); - var dataSource = one.f.switchmanager.staticRouteConfig.data.staticRouteConfigGrid(content); - $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource}) - .on("loaded", function() { - $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll).click(function() { - $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).find(':checkbox').prop('checked', - $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll).is(':checked')); - }); - $(".staticRoute").click(function(e){ - if (!$('.staticRoute[type=checkbox]:not(:checked)').length) { - $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll) - .prop("checked", - true); - } else { - $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll) - .prop("checked", - false); - } - e.stopPropagation(); - }); - }); + body: function() { + var $form = $(document.createElement('form')); + var $fieldset = $(document.createElement('fieldset')); + // static route name + var $label = one.lib.form.label("Name"); + var $input = one.lib.form.input("Name"); + $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.routeName); + $fieldset.append($label).append($input); + // static route IP Mask + var $label = one.lib.form.label("Static Route"); + var $input = one.lib.form.input("Static Route"); + var $help = one.lib.form.help('Example: 53.55.0.0/16'); + $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.staticRoute); + $fieldset.append($label).append($input).append($help); + // static route IP Mask + var $label = one.lib.form.label("Next Hop"); + var $input = one.lib.form.input("Next Hop"); + var $help = one.lib.form.help('Example: 192.168.10.254'); + $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.nextHop); + $fieldset.append($label).append($input).append($help); + // return + $form.append($fieldset); + return $form; + }, + ajax: { + staticRouteConfig: function(requestData, callback) { + $.getJSON(one.f.switchmanager.rootUrl + "/staticRoute/add", requestData, function(data) { + callback(data); }); + } }, - // device ajax calls - ajax : { - main : function(url, requestData, callback) { - $.getJSON(url, requestData, function(data) { - callback(data); - }); - } + data : { + }, - registry: {}, - modal : { - initialize: function() { - var h3 = "Add Static Route"; - var footer = one.f.switchmanager.staticRouteConfig.modal.footer(); - var $modal = one.lib.modal.spawn(one.f.switchmanager.staticRouteConfig.id.modal.modal, h3, "", footer); - // bind save button - $('#' + one.f.switchmanager.staticRouteConfig.id.modal.save, $modal).click(function() { - one.f.switchmanager.staticRouteConfig.modal.save($modal); + footer : function() { + var footer = []; + var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.staticRouteConfig.id.modal.save, "btn-primary", ""); + var $saveButton = one.lib.dashlet.button.button(saveButton); + footer.push($saveButton); + return footer; + }, + removeMultiple: { + dialog: function(routesToDelete) { + var h3 = 'Remove Static Route'; + + var footer = one.f.switchmanager.staticRouteConfig.modal.removeMultiple.footer(); + var $body = one.f.switchmanager.staticRouteConfig.modal.removeMultiple.body(routesToDelete); + var $modal = one.lib.modal.spawn(one.f.switchmanager.staticRouteConfig.id.modal.modal, h3, $body, footer); + + // bind close button + $('#'+one.f.switchmanager.staticRouteConfig.id.modal.cancel, $modal).click(function() { + $modal.modal('hide'); + }); + + // bind remove rule button + $('#'+one.f.switchmanager.staticRouteConfig.id.modal.remove, $modal).click(this, function(e) { + if (routesToDelete.length > 0) { + var requestData = {}; + requestData["routesToDelete"] = routesToDelete.toString(); + var url = one.f.switchmanager.rootUrl + "/staticRoute/delete"; + one.f.switchmanager.staticRouteConfig.ajax.main(url, requestData, function(response) { + $modal.modal('hide'); + if (response.status == true) { + // refresh dashlet by passing dashlet div as param + one.lib.alert("Static Route(s) successfully removed"); + } else { + alert(response.message); + } + one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet")); }); - var $body = one.f.switchmanager.staticRouteConfig.modal.body(); - one.lib.modal.inject.body($modal, $body); - return $modal; - }, - save: function($modal) { - var result = {}; - result['routeName'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.routeName, $modal).val(); - result['staticRoute'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.staticRoute, $modal).val(); - result['nextHop'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.nextHop, $modal).val(); - one.f.switchmanager.staticRouteConfig.modal.ajax.staticRouteConfig(result, function(response) { - if(response.status == true) { - $modal.modal('hide'); - // refresh dashlet by passing dashlet div as param - one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet")); - } else { - // TODO: Show error message in a error message label instead. - alert(response.message); - } - }); - }, - body: function() { - var $form = $(document.createElement('form')); - var $fieldset = $(document.createElement('fieldset')); - // static route name - var $label = one.lib.form.label("Name"); - var $input = one.lib.form.input("Name"); - $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.routeName); - $fieldset.append($label).append($input); - // static route IP Mask - var $label = one.lib.form.label("Static Route"); - var $input = one.lib.form.input("Static Route"); - var $help = one.lib.form.help('Example: 53.55.0.0/16'); - $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.staticRoute); - $fieldset.append($label).append($input).append($help); - // static route IP Mask - var $label = one.lib.form.label("Next Hop"); - var $input = one.lib.form.input("Next Hop"); - var $help = one.lib.form.help('Example: 192.168.10.254'); - $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.nextHop); - $fieldset.append($label).append($input).append($help); - // return - $form.append($fieldset); - return $form; - }, - ajax: { - staticRouteConfig: function(requestData, callback) { - $.getJSON(one.f.switchmanager.rootUrl + "/staticRoute/add", requestData, function(data) { - callback(data); - }); - } - }, - data : { - - }, - footer : function() { - var footer = []; - var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.staticRouteConfig.id.modal.save, "btn-primary", ""); - var $saveButton = one.lib.dashlet.button.button(saveButton); - footer.push($saveButton); - return footer; + } + }); + $modal.modal(); + }, + footer : function() { + var footer = []; + var remove = one.lib.dashlet.button.single('Remove Static Route',one.f.switchmanager.staticRouteConfig.id.modal.remove, 'btn-danger', ''); + var $remove = one.lib.dashlet.button.button(remove); + footer.push($remove); + + var cancel = one.lib.dashlet.button.single('Cancel', one.f.switchmanager.staticRouteConfig.id.modal.cancel, '', ''); + var $cancel = one.lib.dashlet.button.button(cancel); + footer.push($cancel); + + return footer; + }, + body : function (staticRouteList) { + var $p = $(document.createElement('p')); + var p = 'Remove the following Static Route(s)?'; + //creata a BS label for each rule and append to list + $(staticRouteList).each(function(){ + var $span = $(document.createElement('span')); + $span.append(this); + p += '
' + $span[0].outerHTML; + }); + $p.append(p); + return $p; + } + } + }, + // data functions + data : { + staticRouteConfigGrid: function(data) { + var source = new StaticDataSource({ + columns: [ + { + property: 'selector', + label: "", + sortable: false + }, + { + property: 'name', + label: 'Name', + sortable: true + }, + { + property: 'staticRoute', + label: 'Static Route', + sortable: true + }, + { + property: 'nextHop', + label: 'Next Hop Address', + sortable: true + } + ], + data: data.nodeData, + formatter: function(items) { + $.each(items, function(index, item) { + item["selector"] = ''; + }); + }, - removeMultiple: { - dialog: function(routesToDelete) { - var h3 = 'Remove Static Route'; - - var footer = one.f.switchmanager.staticRouteConfig.modal.removeMultiple.footer(); - var $body = one.f.switchmanager.staticRouteConfig.modal.removeMultiple.body(routesToDelete); - var $modal = one.lib.modal.spawn(one.f.switchmanager.staticRouteConfig.id.modal.modal, h3, $body, footer); - - // bind close button - $('#'+one.f.switchmanager.staticRouteConfig.id.modal.cancel, $modal).click(function() { - $modal.modal('hide'); - }); - - // bind remove rule button - $('#'+one.f.switchmanager.staticRouteConfig.id.modal.remove, $modal).click(this, function(e) { - if (routesToDelete.length > 0) { - var requestData = {}; - requestData["routesToDelete"] = routesToDelete.toString(); - var url = one.f.switchmanager.rootUrl + "/staticRoute/delete"; - one.f.switchmanager.staticRouteConfig.ajax.main(url, requestData, function(response) { - $modal.modal('hide'); - if (response.status == true) { - // refresh dashlet by passing dashlet div as param - one.lib.alert("Static Route(s) successfully removed"); - } else { - alert(response.message); - } - one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet")); - }); - } - }); - $modal.modal(); - }, - footer : function() { - var footer = []; - var remove = one.lib.dashlet.button.single('Remove Static Route',one.f.switchmanager.staticRouteConfig.id.modal.remove, 'btn-danger', ''); - var $remove = one.lib.dashlet.button.button(remove); - footer.push($remove); - - var cancel = one.lib.dashlet.button.single('Cancel', one.f.switchmanager.staticRouteConfig.id.modal.cancel, '', ''); - var $cancel = one.lib.dashlet.button.button(cancel); - footer.push($cancel); - - return footer; - }, - body : function (staticRouteList) { - var $p = $(document.createElement('p')); - var p = 'Remove the following Static Route(s)?'; - //creata a BS label for each rule and append to list - $(staticRouteList).each(function(){ - var $span = $(document.createElement('span')); - $span.append(this); - p += '
' + $span[0].outerHTML; - }); - $p.append(p); - return $p; - } - } + delay: 0 + }); + return source; }, - // data functions - data : { - staticRouteConfigGrid: function(data) { - var source = new StaticDataSource({ - columns: [ - { - property: 'selector', - label: "", - sortable: false - }, - { - property: 'name', - label: 'Name', - sortable: true - }, - { - property: 'staticRoute', - label: 'Static Route', - sortable: true - }, - { - property: 'nextHop', - label: 'Next Hop Address', - sortable: true - } - ], - data: data.nodeData, - formatter: function(items) { - $.each(items, function(index, item) { - item["selector"] = ''; - }); - - }, - delay: 0 - }); - return source; - }, - staticRouteConfig : function(data) { - var result = []; - $.each(data.nodeData, function(key, value) { - var tr = {}; - // fill up all the td's - var entry = []; - var checkbox = document.createElement("input"); - checkbox.setAttribute("type", "checkbox"); - checkbox.setAttribute("id", value["name"]); - entry.push(checkbox); - entry.push(value["name"]); - entry.push(value["staticRoute"]); - entry.push(value["nextHop"]); - tr.entry = entry; - result.push(tr); - }); - return result; - } + staticRouteConfig : function(data) { + var result = []; + $.each(data.nodeData, function(key, value) { + var tr = {}; + // fill up all the td's + var entry = []; + var checkbox = document.createElement("input"); + checkbox.setAttribute("type", "checkbox"); + checkbox.setAttribute("id", value["name"]); + entry.push(checkbox); + entry.push(value["name"]); + entry.push(value["staticRoute"]); + entry.push(value["nextHop"]); + tr.entry = entry; + result.push(tr); + }); + return result; } + } } one.f.switchmanager.spanPortConfig = { - id: { - dashlet: { - add: "one_f_switchmanager_spanPortConfig_id_dashlet_add", - remove: "one_f_switchmanager_spanPortConfig_id_dashlet_remove", - datagrid: "one_f_switchmanager_spanPortConfig_id_dashlet_datagrid", - selectAllFlows: "one_f_switchmanager_spanPortConfig_id_dashlet_selectAllFlows" - }, - modal: { - modal: "one_f_switchmanager_spanPortConfig_id_modal_modal", - save: "one_f_switchmanager_spanPortConfig_id_modal_save", - cancel: "one_f_switchmanager_spanPortConfig_id_modal_cancel", - remove: "one_f_switchmanager_spanPortConfig_id_modal_remove", - form: { - name : "one_f_switchmanager_spanPortConfig_id_modal_form_name", - nodes : "one_f_switchmanager_spanPortConfig_id_modal_form_nodes", - port : "one_f_switchmanager_spanPortConfig_id_modal_form_port", + id: { + dashlet: { + add: "one_f_switchmanager_spanPortConfig_id_dashlet_add", + remove: "one_f_switchmanager_spanPortConfig_id_dashlet_remove", + datagrid: "one_f_switchmanager_spanPortConfig_id_dashlet_datagrid", + selectAllFlows: "one_f_switchmanager_spanPortConfig_id_dashlet_selectAllFlows" + }, + modal: { + modal: "one_f_switchmanager_spanPortConfig_id_modal_modal", + save: "one_f_switchmanager_spanPortConfig_id_modal_save", + cancel: "one_f_switchmanager_spanPortConfig_id_modal_cancel", + remove: "one_f_switchmanager_spanPortConfig_id_modal_remove", + form: { + name : "one_f_switchmanager_spanPortConfig_id_modal_form_name", + nodes : "one_f_switchmanager_spanPortConfig_id_modal_form_nodes", + port : "one_f_switchmanager_spanPortConfig_id_modal_form_port", + } + } + }, + dashlet: function($dashlet) { + one.lib.dashlet.empty($dashlet); + + //populate table in dashlet + var url = one.f.switchmanager.rootUrl + "/spanPorts"; + one.f.switchmanager.spanPortConfig.ajax.main(url, {}, function(content) { + + if (content.privilege === 'WRITE') { + + // Add span port button + var button = one.lib.dashlet.button.single("Add SPAN Port", one.f.switchmanager.spanPortConfig.id.dashlet.add, "btn-primary", "btn-mini"); + var $button = one.lib.dashlet.button.button(button); + + $button.click(function() { + var $modal = one.f.switchmanager.spanPortConfig.modal.initialize(); + $modal.modal(); + }); + $dashlet.append(one.lib.dashlet.header(one.f.dashlet.spanPortConfig.name)); + $dashlet.append($button); + + // Delete span port button + var button = one.lib.dashlet.button.single("Remove SPAN Port", one.f.switchmanager.spanPortConfig.id.dashlet.remove, "btn-danger", "btn-mini"); + var $button = one.lib.dashlet.button.button(button); + $button.click(function() { + var spanPortsToDelete = []; + var checkedCheckBoxes = $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).find("tbody input:checked"); + + if (checkedCheckBoxes.size() === 0) { + return false; + } + checkedCheckBoxes.each(function(index, value) { + var spanPortObj = {}; + spanPortObj['spanPortJson'] = decodeURIComponent(checkedCheckBoxes[index].getAttribute("spanPort")); + spanPortObj['spanPortNodeName'] = checkedCheckBoxes[index].getAttribute("spanPortNode"); + spanPortObj['spanPortPortName'] = checkedCheckBoxes[index].getAttribute("spanPortPort"); + + spanPortsToDelete.push(spanPortObj); + }); + one.f.switchmanager.spanPortConfig.modal.removeMultiple.dialog(spanPortsToDelete); + }); + $dashlet.append($button); + } + var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.spanPortConfig.id.dashlet.datagrid, { + searchable: true, + filterable: false, + pagination: true, + flexibleRowsPerPage: true + }, "table-striped table-condensed"); + $dashlet.append($gridHTML); + var dataSource = one.f.switchmanager.spanPortConfig.data.spanPortConfigGrid(content); + $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource}) + .on("loaded", function() { + $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll).click(function() { + $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).find(':checkbox').prop('checked', + $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll).is(':checked')); + }); + $(".spanPortConfig").click(function(e){ + if (!$('.spanPortConfig[type=checkbox]:not(:checked)').length) { + $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll) + .prop("checked", + true); + } else { + $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll) + .prop("checked", + false); } - } + e.stopPropagation(); + }); + }); + }); + }, + // device ajax calls + ajax : { + main : function(url, requestData, callback) { + $.getJSON(url, requestData, function(data) { + callback(data); + }); + } + }, + registry: {}, + modal : { + initialize: function() { + var h3 = "Add SPAN Port"; + var footer = one.f.switchmanager.spanPortConfig.modal.footer(); + var $modal = one.lib.modal.spawn(one.f.switchmanager.spanPortConfig.id.modal.modal, h3, "", footer); + // bind save button + $('#' + one.f.switchmanager.spanPortConfig.id.modal.save, $modal).click(function() { + one.f.switchmanager.spanPortConfig.modal.save($modal); + }); + + one.f.switchmanager.spanPortConfig.modal.ajax.nodes(function(nodes, nodeports) { + var $body = one.f.switchmanager.spanPortConfig.modal.body(nodes, nodeports); + one.lib.modal.inject.body($modal, $body); + }); + return $modal; }, - dashlet: function($dashlet) { - one.lib.dashlet.empty($dashlet); - - //populate table in dashlet - var url = one.f.switchmanager.rootUrl + "/spanPorts"; - one.f.switchmanager.spanPortConfig.ajax.main(url, {}, function(content) { - - if (content.privilege === 'WRITE') { - - // Add span port button - var button = one.lib.dashlet.button.single("Add SPAN Port", one.f.switchmanager.spanPortConfig.id.dashlet.add, "btn-primary", "btn-mini"); - var $button = one.lib.dashlet.button.button(button); - - $button.click(function() { - var $modal = one.f.switchmanager.spanPortConfig.modal.initialize(); - $modal.modal(); - }); - $dashlet.append(one.lib.dashlet.header(one.f.dashlet.spanPortConfig.name)); - $dashlet.append($button); - - // Delete span port button - var button = one.lib.dashlet.button.single("Remove SPAN Port", one.f.switchmanager.spanPortConfig.id.dashlet.remove, "btn-danger", "btn-mini"); - var $button = one.lib.dashlet.button.button(button); - $button.click(function() { - var spanPortsToDelete = []; - var checkedCheckBoxes = $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).find("tbody input:checked"); - - if (checkedCheckBoxes.size() === 0) { - return false; - } - checkedCheckBoxes.each(function(index, value) { - var spanPortObj = {}; - spanPortObj['spanPortJson'] = decodeURIComponent(checkedCheckBoxes[index].getAttribute("spanPort")); - spanPortObj['spanPortNodeName'] = checkedCheckBoxes[index].getAttribute("spanPortNode"); - spanPortObj['spanPortPortName'] = checkedCheckBoxes[index].getAttribute("spanPortPort"); - - spanPortsToDelete.push(spanPortObj); - }); - one.f.switchmanager.spanPortConfig.modal.removeMultiple.dialog(spanPortsToDelete); - }); - $dashlet.append($button); + save: function($modal) { + var result = {}; + result['nodeId'] = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.nodes, $modal).val(); + result['spanPort'] = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.port, $modal).val(); + one.f.switchmanager.spanPortConfig.modal.ajax.saveSpanPortConfig(result, + function(response) { + if(response.status == true) { + $modal.modal('hide'); + one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet")); + } else { + alert(response.message); } - var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.spanPortConfig.id.dashlet.datagrid, { - searchable: true, - filterable: false, - pagination: true, - flexibleRowsPerPage: true - }, "table-striped table-condensed"); - $dashlet.append($gridHTML); - var dataSource = one.f.switchmanager.spanPortConfig.data.spanPortConfigGrid(content); - $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource}) - .on("loaded", function() { - $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll).click(function() { - $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).find(':checkbox').prop('checked', - $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll).is(':checked')); - }); - $(".spanPortConfig").click(function(e){ - if (!$('.spanPortConfig[type=checkbox]:not(:checked)').length) { - $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll) - .prop("checked", - true); - } else { - $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll) - .prop("checked", - false); - } - e.stopPropagation(); - }); - }); + + }); + }, + body: function(nodes, nodeports) { + var $form = $(document.createElement('form')); + var $fieldset = $(document.createElement('fieldset')); + // node + var $label = one.lib.form.label("Node"); + var $select = one.lib.form.select.create(nodes); + one.lib.form.select.prepend($select, { '' : 'Please Select a Node' }); + $select.val($select.find("option:first").val()); + $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.nodes); + + // bind onchange + $select.change(function() { + // retrieve port value + var nodeId = $(this).find('option:selected').attr('value'); + one.f.switchmanager.spanPortConfig.registry['currentNode'] = nodeId; + var $ports = $('#'+one.f.switchmanager.spanPortConfig.id.modal.form.port); + var ports = one.f.switchmanager.spanPortConfig.registry['nodePorts'][nodeId] + var options = {}; + $(ports).each(function(idx, val) { + options[val.internalPortName] = val.portName+' ('+val.portId+')'; + }); + one.lib.form.select.inject($ports, options); + one.lib.form.select.prepend($ports, {'':'Please Select a Port'}); + $ports.val($ports.find('option:first').val()); + }); + + $fieldset.append($label).append($select); + // input port + var $label = one.lib.form.label("Input Port"); + var $select = one.lib.form.select.create(); + one.lib.form.select.prepend($select, {'':'None'}); + $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.port); + $select.val($select.find('option:first').val()); + $fieldset.append($label).append($select); + + // return + $form.append($fieldset); + return $form; + }, + ajax: { + nodes: function(callback) { + $.getJSON(one.f.switchmanager.rootUrl + "/nodeports", function(data) { + var nodes = {}; + var nodePorts = {}; + $(data).each(function(index, node) { + nodes[node.nodeId] = node.nodeName; + nodePorts[node.nodeId] = node.nodePorts; + }); + one.f.switchmanager.spanPortConfig.registry['nodePorts'] = nodePorts; + callback(nodes, nodePorts); }); + }, + saveSpanPortConfig: function(requestData, callback) { + var resource = {}; + resource["jsonData"] = JSON.stringify(requestData); + $.getJSON(one.f.switchmanager.rootUrl + "/spanPorts/add", resource, function(data) { + callback(data); + }); + } }, - // device ajax calls - ajax : { - main : function(url, requestData, callback) { - $.getJSON(url, requestData, function(data) { - callback(data); - }); - } + footer : function() { + var footer = []; + var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.spanPortConfig.id.modal.save, "btn-primary", ""); + var $saveButton = one.lib.dashlet.button.button(saveButton); + footer.push($saveButton); + return footer; }, - registry: {}, - modal : { - initialize: function() { - var h3 = "Add SPAN Port"; - var footer = one.f.switchmanager.spanPortConfig.modal.footer(); - var $modal = one.lib.modal.spawn(one.f.switchmanager.spanPortConfig.id.modal.modal, h3, "", footer); - // bind save button - $('#' + one.f.switchmanager.spanPortConfig.id.modal.save, $modal).click(function() { - one.f.switchmanager.spanPortConfig.modal.save($modal); - }); + removeMultiple: { + dialog: function(spanPortsToDelete) { + var h3 = 'Remove SPAN Port'; - one.f.switchmanager.spanPortConfig.modal.ajax.nodes(function(nodes, nodeports) { - var $body = one.f.switchmanager.spanPortConfig.modal.body(nodes, nodeports); - one.lib.modal.inject.body($modal, $body); - }); - return $modal; - }, - save: function($modal) { - var result = {}; - result['nodeId'] = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.nodes, $modal).val(); - result['spanPort'] = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.port, $modal).val(); - one.f.switchmanager.spanPortConfig.modal.ajax.saveSpanPortConfig(result, - function(response) { - if(response.status == true) { - $modal.modal('hide'); - one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet")); - } else { - alert(response.message); - } - - }); - }, - body: function(nodes, nodeports) { - var $form = $(document.createElement('form')); - var $fieldset = $(document.createElement('fieldset')); - // node - var $label = one.lib.form.label("Node"); - var $select = one.lib.form.select.create(nodes); - one.lib.form.select.prepend($select, { '' : 'Please Select a Node' }); - $select.val($select.find("option:first").val()); - $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.nodes); - - // bind onchange - $select.change(function() { - // retrieve port value - var nodeId = $(this).find('option:selected').attr('value'); - one.f.switchmanager.spanPortConfig.registry['currentNode'] = nodeId; - var $ports = $('#'+one.f.switchmanager.spanPortConfig.id.modal.form.port); - var ports = one.f.switchmanager.spanPortConfig.registry['nodePorts'][nodeId] - var options = {}; - $(ports).each(function(idx, val) { - options[val.internalPortName] = val.portName+' ('+val.portId+')'; - }); - one.lib.form.select.inject($ports, options); - one.lib.form.select.prepend($ports, {'':'Please Select a Port'}); - $ports.val($ports.find('option:first').val()); - }); + var footer = one.f.switchmanager.spanPortConfig.modal.removeMultiple.footer(); + var $body = one.f.switchmanager.spanPortConfig.modal.removeMultiple.body(spanPortsToDelete); + var $modal = one.lib.modal.spawn(one.f.switchmanager.spanPortConfig.id.modal.modal, h3, $body, footer); - $fieldset.append($label).append($select); - // input port - var $label = one.lib.form.label("Input Port"); - var $select = one.lib.form.select.create(); - one.lib.form.select.prepend($select, {'':'None'}); - $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.port); - $select.val($select.find('option:first').val()); - $fieldset.append($label).append($select); - - // return - $form.append($fieldset); - return $form; - }, - ajax: { - nodes: function(callback) { - $.getJSON(one.f.switchmanager.rootUrl + "/nodeports", function(data) { - var nodes = {}; - var nodePorts = {}; - $(data).each(function(index, node) { - nodes[node.nodeId] = node.nodeName; - nodePorts[node.nodeId] = node.nodePorts; - }); - one.f.switchmanager.spanPortConfig.registry['nodePorts'] = nodePorts; - callback(nodes, nodePorts); - }); - }, - saveSpanPortConfig: function(requestData, callback) { - var resource = {}; - resource["jsonData"] = JSON.stringify(requestData); - $.getJSON(one.f.switchmanager.rootUrl + "/spanPorts/add", resource, function(data) { - callback(data); - }); - } - }, - footer : function() { - var footer = []; - var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.spanPortConfig.id.modal.save, "btn-primary", ""); - var $saveButton = one.lib.dashlet.button.button(saveButton); - footer.push($saveButton); - return footer; - }, - removeMultiple: { - dialog: function(spanPortsToDelete) { - var h3 = 'Remove SPAN Port'; - - var footer = one.f.switchmanager.spanPortConfig.modal.removeMultiple.footer(); - var $body = one.f.switchmanager.spanPortConfig.modal.removeMultiple.body(spanPortsToDelete); - var $modal = one.lib.modal.spawn(one.f.switchmanager.spanPortConfig.id.modal.modal, h3, $body, footer); - - // bind close button - $('#'+one.f.switchmanager.spanPortConfig.id.modal.cancel, $modal).click(function() { - $modal.modal('hide'); - }); - - // bind remove rule button - $('#'+one.f.switchmanager.spanPortConfig.id.modal.remove, $modal).click(this, function(e) { - var requestData = {}; - var spanPorts = []; - $(spanPortsToDelete).each(function(index, spanPort) { - spanPorts.push(JSON.parse(spanPort.spanPortJson)); - }); - requestData["spanPortsToDelete"] = JSON.stringify(spanPorts); - - var url = one.f.switchmanager.rootUrl + "/spanPorts/delete"; - one.f.switchmanager.spanPortConfig.ajax.main(url, requestData, function(response) { - $modal.modal('hide'); - if (response.status == true) { - // refresh dashlet by passing dashlet div as param - one.lib.alert("Span Port(s) successfully removed"); - } else { - alert(response.message); - } - one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet")); - }); - }); - $modal.modal(); - }, - footer : function() { - var footer = []; - var remove = one.lib.dashlet.button.single('Remove SPAN Port',one.f.switchmanager.spanPortConfig.id.modal.remove, 'btn-danger', ''); - var $remove = one.lib.dashlet.button.button(remove); - footer.push($remove); - - var cancel = one.lib.dashlet.button.single('Cancel', one.f.switchmanager.spanPortConfig.id.modal.cancel, '', ''); - var $cancel = one.lib.dashlet.button.button(cancel); - footer.push($cancel); - - return footer; - }, - body : function (spanPortToDelete) { - var $p = $(document.createElement('p')); - var p = 'Remove the following Span Port(s)?'; - //creata a BS label for each rule and append to list - - $(spanPortToDelete).each(function(index, spanPortItem) { - var $span = $(document.createElement('span')); - $span.append(this.spanPortNodeName+"-"+this.spanPortPortName); - p += '
' + $span[0].outerHTML; - }); - $p.append(p); - return $p; + // bind close button + $('#'+one.f.switchmanager.spanPortConfig.id.modal.cancel, $modal).click(function() { + $modal.modal('hide'); + }); + + // bind remove rule button + $('#'+one.f.switchmanager.spanPortConfig.id.modal.remove, $modal).click(this, function(e) { + var requestData = {}; + var spanPorts = []; + $(spanPortsToDelete).each(function(index, spanPort) { + spanPorts.push(JSON.parse(spanPort.spanPortJson)); + }); + requestData["spanPortsToDelete"] = JSON.stringify(spanPorts); + + var url = one.f.switchmanager.rootUrl + "/spanPorts/delete"; + one.f.switchmanager.spanPortConfig.ajax.main(url, requestData, function(response) { + $modal.modal('hide'); + if (response.status == true) { + // refresh dashlet by passing dashlet div as param + one.lib.alert("Span Port(s) successfully removed"); + } else { + alert(response.message); } - } + one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet")); + }); + }); + $modal.modal(); + }, + footer : function() { + var footer = []; + var remove = one.lib.dashlet.button.single('Remove SPAN Port',one.f.switchmanager.spanPortConfig.id.modal.remove, 'btn-danger', ''); + var $remove = one.lib.dashlet.button.button(remove); + footer.push($remove); + + var cancel = one.lib.dashlet.button.single('Cancel', one.f.switchmanager.spanPortConfig.id.modal.cancel, '', ''); + var $cancel = one.lib.dashlet.button.button(cancel); + footer.push($cancel); + + return footer; + }, + body : function (spanPortToDelete) { + var $p = $(document.createElement('p')); + var p = 'Remove the following Span Port(s)?'; + //creata a BS label for each rule and append to list + + $(spanPortToDelete).each(function(index, spanPortItem) { + var $span = $(document.createElement('span')); + $span.append(this.spanPortNodeName+"-"+this.spanPortPortName); + p += '
' + $span[0].outerHTML; + }); + $p.append(p); + return $p; + } + } + }, + // data functions + data : { + spanPortConfigGrid: function(data) { + var source = new StaticDataSource({ + columns: [ + { + property: 'selector', + label: "", + sortable: false + }, + { + property: 'nodeName', + label: 'Node', + sortable: true + }, + { + property: 'spanPortName', + label: 'SPAN Port', + sortable: true + }, + ], + data: data.nodeData, + formatter: function(items) { + $.each(items, function(index, item) { + item["selector"] = ''; + }); + }, + delay: 0 + }); + return source; }, - // data functions - data : { - spanPortConfigGrid: function(data) { - var source = new StaticDataSource({ - columns: [ - { - property: 'selector', - label: "", - sortable: false - }, - { - property: 'nodeName', - label: 'Node', - sortable: true - }, - { - property: 'spanPortName', - label: 'SPAN Port', - sortable: true - }, - ], - data: data.nodeData, - formatter: function(items) { - $.each(items, function(index, item) { - item["selector"] = ''; - }); - }, - delay: 0 - }); - return source; - }, - devices : function(data) { - var result = []; - $.each(data.nodeData, function(key, value) { - var tr = {}; - // fill up all the td's - var entry = []; - var checkbox = document.createElement("input"); - checkbox.setAttribute("type", "checkbox"); - checkbox.spanPort = value.json; - entry.push(checkbox); - entry.push(value["nodeName"]); - entry.push(value["spanPort"]); - tr.entry = entry; - result.push(tr); - }); - return result; + devices : function(data) { + var result = []; + $.each(data.nodeData, function(key, value) { + var tr = {}; + // fill up all the td's + var entry = []; + var checkbox = document.createElement("input"); + checkbox.setAttribute("type", "checkbox"); + checkbox.spanPort = value.json; + entry.push(checkbox); + entry.push(value["nodeName"]); + entry.push(value["spanPort"]); + tr.entry = entry; + result.push(tr); + }); + return result; + } + } +} + +one.f.connection = { + id : { // one.f.connection.id + datagrid : 'one-f-connection-id-datagrid', + add : 'one-f-connection-id-add' + }, + dashlet: function($dashlet) { + one.lib.dashlet.empty($dashlet); + // heading + $dashlet.append(one.lib.dashlet.header(one.f.dashlet.connection.name)); + // add button + var add = one.lib.dashlet.button.single('Add Node', one.f.connection.id.add, 'btn-primary', 'btn-mini'); + var $add = one.lib.dashlet.button.button(add); + $add.click(function() { + one.f.connection.add.initialize(); + }); + $dashlet.append($add); + // load table + var url = one.f.switchmanager.rootUrl+'/connect/nodes'; + $.getJSON(url, function(data) { + var $gridHTML = one.lib.dashlet.datagrid.init(one.f.connection.id.datagrid, { + searchable: true, + filterable: false, + pagination: true, + flexibleRowsPerPage: true + }, 'table-striped table-condensed table-cursor'); + $dashlet.append($gridHTML); + var dataSource = one.f.connection.data(data); + $('#'+one.f.connection.id.datagrid, $dashlet).datagrid({dataSource:dataSource}) + .on('loaded', function() { + $(this).find('tbody tr').click(function() { + var nodeId = $(this).find('.nodeId').text(); + var nodeType = $(this).find('.nodeType').text(); + var nodeName = $(this).find('.nodeName').text(); + one.f.connection.remove.initialize(nodeId, nodeName, nodeType); + }); + }); + }); + }, + data : function(data) { + var source = new StaticDataSource({ + columns: [ + { + property: 'nodeName', + label: 'Node', + sortable: true + } + ], + data: data, + formatter: function(items) { + $.each(items, function(index, item) { + var $nodeId = $(document.createElement('span')); + $nodeId.css('display', 'none'); + var $nodeType = $nodeId.clone(); + var $nodeName = $nodeId.clone(); + $nodeId.append(item.nodeId).addClass('nodeId'); + $nodeType.append(item.nodeType).addClass('nodeType'); + $nodeName.append(item.nodeName).addClass('nodeName'); + item.nodeName += $nodeId[0].outerHTML+$nodeType[0].outerHTML+$nodeName[0].outerHTML; + }); + }, + delay: 0 + }); + return source; + }, + add : { + id : { // one.f.connection.add.id + modal : 'one-f-connection-add-id-modal', + add : 'one-f-connection-add-id-add', + cancel : 'one-f-connection-add-id-cancel', + form : { + nodeId : 'one-f-connection-add-id-form-nodeId', + ipAddress : 'one-f-connection-add-id-form-ipAddress', + port : 'one-f-connection-add-id-form-port', + nodeType : 'one-f-connection-add-id-form-nodeType' + } + }, + initialize : function() { + var h3 = 'Add Node'; + var footer = one.f.connection.add.footer(); + var $body = one.f.connection.add.body();; + var $modal = one.lib.modal.spawn(one.f.connection.add.id.modal, h3, $body, footer); + // bind add buton + $('#'+one.f.connection.add.id.add, $modal).click(function() { + var nodeId = $('#'+one.f.connection.add.id.form.nodeId, $modal).val(); + if (nodeId === '') { + alert('Please enter a node ID'); + return false; + } + var resources = {}; + resources.ipAddress = $('#'+one.f.connection.add.id.form.ipAddress, $modal).val(); + if (resources.ipAddress === '') { + alert('Please enter an IP Address'); + return false; + } + resources.port = $('#'+one.f.connection.add.id.form.port, $modal).val(); + if (resources.port === '') { + alert('Please enter a port'); + return false; + } + var nodeType = $('#'+one.f.connection.add.id.form.nodeType, $modal).val(); + if (nodeType !== '') { + resources.nodeType = nodeType; } + var url = one.f.switchmanager.rootUrl+'/connect/'+encodeURI(nodeId); + $.post(url, resources, function(result) { + if (result.success === true) { + $modal.modal('hide'); + one.lib.alert(result.description); + } else { + alert(result.code+': '+result.description); + } + }); + }); + // bind cancel button + $('#'+one.f.connection.add.id.cancel, $modal).click(function() { + $modal.modal('hide'); + }); + $modal.modal(); + }, + body : function() { + var $form = $(document.createElement('form')); + var $fieldset = $(document.createElement('fieldset')); + // node id + var $label = one.lib.form.label('Node ID'); + var $input = one.lib.form.input('Node ID'); + $input.attr('id', one.f.connection.add.id.form.nodeId); + $fieldset.append($label).append($input); + // ip address + $label = one.lib.form.label('IP Address'); + $input = one.lib.form.input('IP Address'); + $input.attr('id', one.f.connection.add.id.form.ipAddress); + $fieldset.append($label).append($input); + // port + $label = one.lib.form.label('Port'); + $input = one.lib.form.input('Port'); + $input.attr('id', one.f.connection.add.id.form.port); + var $help = one.lib.form.help('Enter a number'); + $fieldset.append($label).append($input).append($help); + // node type + $label = one.lib.form.label('Node Type'); + $input = one.lib.form.input('Node Type'); + $input.attr('id', one.f.connection.add.id.form.nodeType); + $help = one.lib.form.help('Optional'); + $fieldset.append($label).append($input).append($help); + $form.append($fieldset); + return $form; + }, + footer : function() { + var footer = []; + var add = one.lib.dashlet.button.single('Submit', one.f.connection.add.id.add, 'btn-primary', ''); + var $add = one.lib.dashlet.button.button(add); + footer.push($add); + var cancel = one.lib.dashlet.button.single('Cancel', one.f.connection.add.id.cancel, '', ''); + var $cancel = one.lib.dashlet.button.button(cancel); + footer.push($cancel); + return footer; } + }, + remove : { + id : { // one.f.connection.remove.id + modal : 'one-f-connection-remove-id-modal', + remove : 'one-f-connection-remove-id-remove', + cancel : 'one-f-connection-remove-id-cancel' + }, + initialize : function(nodeId, nodeName, nodeType) { + var h3 = 'Remove Node'; + var footer = one.f.connection.remove.footer(); + var $body = one.f.connection.remove.body(nodeName); + var $modal = one.lib.modal.spawn(one.f.connection.remove.id.modal, h3, $body, footer); + // bind remove buton + $('#'+one.f.connection.remove.id.remove, $modal).click(function() { + var resources = {}; + resources.nodeType = nodeType; + var url = one.f.switchmanager.rootUrl+'/disconnect/'+encodeURI(nodeId); + $.post(url, resources, function(result) { + if (result.success === true) { + $modal.modal('hide'); + one.lib.alert(result.description); + } else { + alert(result.code+': '+result.description); + } + }).fail(function() { debugger; }); + }); + // bind cancel button + $('#'+one.f.connection.remove.id.cancel, $modal).click(function() { + $modal.modal('hide'); + }); + $modal.modal(); + }, + body : function(nodeName) { + var $p = $(document.createElement('p')); + $p.append('Remove the following node? '); + var $span = $(document.createElement('span')); + $span.addClass('label label-info'); + $span.append(nodeName); + $p.append($span[0].outerHTML); + return $p; + }, + footer : function() { + var footer = []; + var remove = one.lib.dashlet.button.single('Remove', one.f.connection.remove.id.remove, 'btn-danger', ''); + var $remove = one.lib.dashlet.button.button(remove); + footer.push($remove); + var cancel = one.lib.dashlet.button.single('Cancel', one.f.connection.remove.id.cancel, '', ''); + var $cancel = one.lib.dashlet.button.button(cancel); + footer.push($cancel); + return footer; + } + } } /** INIT **/ // populate nav tabs $(one.f.menu.left.top).each(function(index, value) { - var $nav = $(".nav", "#left-top"); - one.main.page.dashlet($nav, value); + var $nav = $(".nav", "#left-top"); + one.main.page.dashlet($nav, value); }); $(one.f.menu.left.bottom).each(function(index, value) { - var $nav = $(".nav", "#left-bottom"); - one.main.page.dashlet($nav, value); + var $nav = $(".nav", "#left-bottom"); + one.main.page.dashlet($nav, value); }); $(one.f.menu.right.bottom).each(function(index, value) { - var $nav = $(".nav", "#right-bottom"); - one.main.page.dashlet($nav, value); + var $nav = $(".nav", "#right-bottom"); + one.main.page.dashlet($nav, value); }); one.f.addPopOut = function() { - $img1 = $(document.createElement("img")); - $img1.attr("src", "/img/Expand16T.png"); - $img1.attr("style", "float: right;"); - $img1.hover(function() { - $img1.css("cursor", "pointer"); + $img1 = $(document.createElement("img")); + $img1.attr("src", "/img/Expand16T.png"); + $img1.attr("style", "float: right;"); + $img1.hover(function() { + $img1.css("cursor", "pointer"); + }); + $img1.click(function() { + var $modal = one.f.switchmanager.nodesLearnt.modal.initialize.popout(); + $modal.css({ + 'margin-left': '-45%', + 'margin-top': '-3%', + 'width':$(document).width() * 0.8, + 'height':$(document).height() * 0.9 }); - $img1.click(function() { - var $modal = one.f.switchmanager.nodesLearnt.modal.initialize.popout(); - $modal.css({ - 'margin-left': '-45%', - 'margin-top': '-3%', - 'width':$(document).width() * 0.8, - 'height':$(document).height() * 0.9 - }); - $(".modal-body", $modal).css({ - "max-height": $(document).height() * 0.75, - }); - $modal.modal(); + $(".modal-body", $modal).css({ + "max-height": $(document).height() * 0.75, }); - $dash1 = $($("#left-top .nav")[0]); - $dash1.append($img1); + $modal.modal(); + }); + $dash1 = $($("#left-top .nav")[0]); + $dash1.append($img1); }; one.f.addPopOut(); // bind dashlet nav $('.dash .nav a', '#main').click(function() { - // de/activation - var $li = $(this).parent(); - var $ul = $li.parent(); - one.lib.nav.unfocus($ul); - $li.addClass('active'); - // clear respective dashlet - var $dashlet = $ul.parent().find('.dashlet'); - one.lib.dashlet.empty($dashlet); + // de/activation + var $li = $(this).parent(); + var $ul = $li.parent(); + one.lib.nav.unfocus($ul); + $li.addClass('active'); + // clear respective dashlet + var $dashlet = $ul.parent().find('.dashlet'); + one.lib.dashlet.empty($dashlet); - // callback based on menu - var id = $(this).attr('id'); - var menu = one.f.dashlet; - switch (id) { - case menu.nodesLearnt.id: - one.f.switchmanager.nodesLearnt.dashlet($dashlet); - break; - case menu.staticRouteConfig.id: - one.f.switchmanager.staticRouteConfig.dashlet($dashlet); - break; - case menu.subnetGatewayConfig.id: - one.f.switchmanager.subnetGatewayConfig.dashlet($dashlet); - break; - case menu.spanPortConfig.id: - one.f.switchmanager.spanPortConfig.dashlet($dashlet); - break; - }; + // callback based on menu + var id = $(this).attr('id'); + var menu = one.f.dashlet; + switch (id) { + case menu.nodesLearnt.id: + one.f.switchmanager.nodesLearnt.dashlet($dashlet); + break; + case menu.staticRouteConfig.id: + one.f.switchmanager.staticRouteConfig.dashlet($dashlet); + break; + case menu.subnetGatewayConfig.id: + one.f.switchmanager.subnetGatewayConfig.dashlet($dashlet); + break; + case menu.spanPortConfig.id: + one.f.switchmanager.spanPortConfig.dashlet($dashlet); + break; + case menu.connection.id: + one.f.connection.dashlet($dashlet); + break; + }; }); // activate first tab on each dashlet $('.dash .nav').each(function(index, value) { - $($(value).find('li')[0]).find('a').click(); + $($(value).find('li')[0]).find('a').click(); }); diff --git a/third-party/ganymed/src/main/java/ch/ethz/ssh2/Connection.java b/third-party/ganymed/src/main/java/ch/ethz/ssh2/Connection.java index 786f81ce06..aa13c40d9d 100644 --- a/third-party/ganymed/src/main/java/ch/ethz/ssh2/Connection.java +++ b/third-party/ganymed/src/main/java/ch/ethz/ssh2/Connection.java @@ -7,6 +7,7 @@ package ch.ethz.ssh2; import java.io.CharArrayWriter; import java.io.File; +import java.net.Socket; import java.io.FileReader; import java.io.IOException; import java.net.InetSocketAddress;