ONOS-2184 - add virtual network host service.

Change-Id: I06922cb1fbd5d351d62215ae2d84b85e15853585
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkHostService.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkHostService.java
new file mode 100644
index 0000000..6642c5a
--- /dev/null
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkHostService.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.impl;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.incubator.net.virtual.VirtualHost;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+
+import java.util.Collection;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Host service implementation built on the virtual network service.
+ */
+public class VirtualNetworkHostService extends AbstractListenerManager<HostEvent, HostListener>
+        implements HostService, VnetService {
+
+    private static final String NETWORK_NULL = "Network ID cannot be null";
+    private static final String HOST_NULL = "Host ID cannot be null";
+
+    private final VirtualNetwork network;
+    private final VirtualNetworkService manager;
+
+    /**
+     * Creates a new virtual network host service object.
+     *
+     * @param virtualNetworkManager virtual network manager service
+     * @param network               virtual network
+     */
+    public VirtualNetworkHostService(VirtualNetworkService virtualNetworkManager, VirtualNetwork network) {
+        checkNotNull(network, NETWORK_NULL);
+        this.network = network;
+        this.manager = virtualNetworkManager;
+    }
+
+
+    @Override
+    public int getHostCount() {
+        return manager.getVirtualHosts(this.network.id()).size();
+    }
+
+    @Override
+    public Iterable<Host> getHosts() {
+        return getHostsColl();
+    }
+
+    @Override
+    public Host getHost(HostId hostId) {
+        checkNotNull(hostId, HOST_NULL);
+        Optional<VirtualHost> foundHost =  manager.getVirtualHosts(this.network.id())
+                .stream()
+                .filter(host -> hostId.equals(host.id()))
+                .findFirst();
+        if (foundHost.isPresent()) {
+            return foundHost.get();
+        }
+        return null;
+    }
+
+    /**
+     * Gets a collection of virtual hosts.
+     *
+     * @return collection of virtual hosts.
+     */
+    private Collection<Host> getHostsColl() {
+        return manager.getVirtualHosts(this.network.id()).stream().collect(Collectors.toSet());
+    }
+
+    /**
+     * Filters specified collection.
+     *
+     * @param collection collection of hosts to filter
+     * @param predicate condition to filter on
+     * @return collection of virtual hosts that satisfy the filter condition
+     */
+    private Set<Host> filter(Collection<Host> collection, Predicate<Host> predicate) {
+        return collection.stream().filter(predicate).collect(Collectors.toSet());
+    }
+
+    @Override
+    public Set<Host> getHostsByVlan(VlanId vlanId) {
+        checkNotNull(vlanId, "VLAN identifier cannot be null");
+        return filter(getHostsColl(), host -> Objects.equals(host.vlan(), vlanId));
+    }
+
+    @Override
+    public Set<Host> getHostsByMac(MacAddress mac) {
+        checkNotNull(mac, "MAC address cannot be null");
+        return filter(getHostsColl(), host -> Objects.equals(host.mac(), mac));
+    }
+
+    @Override
+    public Set<Host> getHostsByIp(IpAddress ip) {
+        checkNotNull(ip, "IP address cannot be null");
+        return filter(getHostsColl(), host -> host.ipAddresses().contains(ip));
+    }
+
+    @Override
+    public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
+        checkNotNull(connectPoint, "Connect point cannot be null");
+        return filter(getHostsColl(), host -> host.location().equals(connectPoint));
+    }
+
+    @Override
+    public Set<Host> getConnectedHosts(DeviceId deviceId) {
+        checkNotNull(deviceId, "Device identifier cannot be null");
+        return filter(getHostsColl(), host -> host.location().deviceId().equals(deviceId));
+    }
+
+    @Override
+    public void startMonitoringIp(IpAddress ip) {
+        //TODO check what needs to be done here
+    }
+
+    @Override
+    public void stopMonitoringIp(IpAddress ip) {
+        //TODO check what needs to be done here
+    }
+
+    @Override
+    public void requestMac(IpAddress ip) {
+        //TODO check what needs to be done here
+    }
+
+    @Override
+    public VirtualNetwork network() {
+        return network;
+    }
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
index 281dd4a..71d73f9 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
@@ -52,6 +52,7 @@
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.host.HostService;
 import org.onosproject.net.intent.IntentEvent;
 import org.onosproject.net.intent.IntentListener;
 import org.onosproject.net.intent.IntentService;
@@ -338,6 +339,8 @@
             service = new VirtualNetworkTopologyService(this, network);
         } else if (serviceKey.serviceClass.equals(IntentService.class)) {
             service = new VirtualNetworkIntentService(this, network, new DefaultServiceDirectory());
+        } else if (serviceKey.serviceClass.equals(HostService.class)) {
+            service = new VirtualNetworkHostService(this, network);
         } else {
             return null;
         }
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/TestCoreService.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/TestCoreService.java
new file mode 100644
index 0000000..40da02d
--- /dev/null
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/TestCoreService.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.impl;
+
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.core.IdGenerator;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Core service test class.
+ */
+class TestCoreService extends CoreServiceAdapter {
+
+    @Override
+    public IdGenerator getIdGenerator(String topic) {
+        return new IdGenerator() {
+            private AtomicLong counter = new AtomicLong(0);
+
+            @Override
+            public long getNewId() {
+                return counter.getAndIncrement();
+            }
+        };
+    }
+}
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkHostServiceTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkHostServiceTest.java
new file mode 100644
index 0000000..fa21998
--- /dev/null
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkHostServiceTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.impl;
+
+import com.google.common.collect.Iterators;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.junit.TestUtils;
+import org.onosproject.common.event.impl.TestEventDispatcher;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualHost;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.TestDeviceParams;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.intent.FakeIntentManager;
+import org.onosproject.net.intent.TestableIntentService;
+import org.onosproject.store.service.TestStorageService;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import static org.junit.Assert.*;
+
+/**
+ * Junit tests for VirtualNetworkHostService.
+ */
+public class VirtualNetworkHostServiceTest extends TestDeviceParams {
+    private final String tenantIdValue1 = "TENANT_ID1";
+
+    private VirtualNetworkManager manager;
+    private DistributedVirtualNetworkStore virtualNetworkManagerStore;
+    private TestableIntentService intentService = new FakeIntentManager();
+
+    @Before
+    public void setUp() throws Exception {
+        virtualNetworkManagerStore = new DistributedVirtualNetworkStore();
+
+        CoreService coreService = new TestCoreService();
+        virtualNetworkManagerStore.setCoreService(coreService);
+        TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService());
+        virtualNetworkManagerStore.activate();
+
+        manager = new VirtualNetworkManager();
+        manager.store = virtualNetworkManagerStore;
+        manager.intentService = intentService;
+        NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());
+        manager.activate();
+    }
+
+    @After
+    public void tearDown() {
+        virtualNetworkManagerStore.deactivate();
+        manager.deactivate();
+        NetTestTools.injectEventDispatcher(manager, null);
+    }
+
+    /**
+     * Sets up a virtual network with hosts.
+     *
+     * @return virtual network
+     */
+    private VirtualNetwork setupVnet() {
+        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
+        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
+        manager.createVirtualHost(virtualNetwork.id(), HID1, MAC1, VLAN1, LOC1, IPSET1);
+        manager.createVirtualHost(virtualNetwork.id(), HID2, MAC2, VLAN2, LOC2, IPSET2);
+        return virtualNetwork;
+    }
+
+    /**
+     * Sets up a virtual network with no hosts.
+     *
+     * @return virtual network
+     */
+    private VirtualNetwork setupEmptyVnet() {
+        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
+        return manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
+    }
+
+    /**
+     * Tests the getHosts(), getHost(), getHostsByXX(), getConnectedHosts() methods
+     * on a non-empty virtual network.
+     */
+    @Test
+    public void testGetHostsOnNonEmptyVnet() {
+        VirtualNetwork virtualNetwork = setupEmptyVnet();
+        VirtualHost vhost1 = manager.createVirtualHost(virtualNetwork.id(), HID1, MAC1, VLAN1, LOC1, IPSET1);
+        VirtualHost vhost2 = manager.createVirtualHost(virtualNetwork.id(), HID2, MAC2, VLAN2, LOC2, IPSET2);
+        HostService hostService = manager.get(virtualNetwork.id(), HostService.class);
+
+        // test the getHosts() and getHostCount() methods
+        Iterator<Host> itHosts = hostService.getHosts().iterator();
+        assertEquals("The host set size did not match.", 2, Iterators.size(itHosts));
+        assertEquals("The host count did not match.", 2, hostService.getHostCount());
+
+        // test the getHost() method
+        Host testHost = hostService.getHost(HID2);
+        assertEquals("The expected host did not match.", vhost2, testHost);
+
+        // test the getHostsByVlan(...) method
+        Collection<Host> collHost = hostService.getHostsByVlan(VLAN1);
+        assertEquals("The host set size did not match.", 1, collHost.size());
+        assertTrue("The host did not match.", collHost.contains(vhost1));
+
+        // test the getHostsByMac(...) method
+        collHost = hostService.getHostsByMac(MAC2);
+        assertEquals("The host set size did not match.", 1, collHost.size());
+        assertTrue("The host did not match.", collHost.contains(vhost2));
+
+        // test the getHostsByIp(...) method
+        collHost = hostService.getHostsByIp(IP1);
+        assertEquals("The host set size did not match.", 2, collHost.size());
+        collHost = hostService.getHostsByIp(IP2);
+        assertEquals("The host set size did not match.", 1, collHost.size());
+        assertTrue("The host did not match.", collHost.contains(vhost1));
+
+        // test the getConnectedHosts(ConnectPoint) method
+        collHost = hostService.getConnectedHosts(LOC1);
+        assertEquals("The host set size did not match.", 1, collHost.size());
+        assertTrue("The host did not match.", collHost.contains(vhost1));
+
+        // test the getConnectedHosts(DeviceId) method
+        collHost = hostService.getConnectedHosts(DID2);
+        assertEquals("The host set size did not match.", 1, collHost.size());
+        assertTrue("The host did not match.", collHost.contains(vhost2));
+    }
+
+    /**
+     * Tests the getHosts(), getHost(), getHostsByXX(), getConnectedHosts() methods
+     * on an empty virtual network.
+     */
+    @Test
+    public void testGetHostsOnEmptyVnet() {
+        VirtualNetwork virtualNetwork = setupEmptyVnet();
+        HostService hostService = manager.get(virtualNetwork.id(), HostService.class);
+
+        // test the getHosts() and getHostCount() methods
+        Iterator<Host> itHosts = hostService.getHosts().iterator();
+        assertEquals("The host set size did not match.", 0, Iterators.size(itHosts));
+        assertEquals("The host count did not match.", 0, hostService.getHostCount());
+
+        // test the getHost() method
+        Host testHost = hostService.getHost(HID2);
+        assertNull("The host should be null.", testHost);
+
+        // test the getHostsByVlan(...) method
+        Collection<Host> collHost = hostService.getHostsByVlan(VLAN1);
+        assertEquals("The host set size did not match.", 0, collHost.size());
+
+        // test the getHostsByMac(...) method
+        collHost = hostService.getHostsByMac(MAC2);
+        assertEquals("The host set size did not match.", 0, collHost.size());
+
+        // test the getHostsByIp(...) method
+        collHost = hostService.getHostsByIp(IP1);
+        assertEquals("The host set size did not match.", 0, collHost.size());
+
+        // test the getConnectedHosts(ConnectPoint) method
+        collHost = hostService.getConnectedHosts(LOC1);
+        assertEquals("The host set size did not match.", 0, collHost.size());
+
+        // test the getConnectedHosts(DeviceId) method
+        collHost = hostService.getConnectedHosts(DID2);
+        assertEquals("The host set size did not match.", 0, collHost.size());
+    }
+
+    /**
+     * Tests querying for a host using a null host identifier.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testGetHostByNullId() {
+        VirtualNetwork vnet = setupEmptyVnet();
+        HostService hostService = manager.get(vnet.id(), HostService.class);
+
+        hostService.getHost(null);
+    }
+
+    /**
+     * Tests querying for hosts with null mac.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testGetHostsByNullMac() {
+        VirtualNetwork vnet = setupEmptyVnet();
+        HostService hostService = manager.get(vnet.id(), HostService.class);
+
+        hostService.getHostsByMac(null);
+    }
+
+    /**
+     * Tests querying for hosts with null vlan.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testGetHostsByNullVlan() {
+        VirtualNetwork vnet = setupEmptyVnet();
+        HostService hostService = manager.get(vnet.id(), HostService.class);
+
+        hostService.getHostsByVlan(null);
+    }
+
+    /**
+     * Tests querying for hosts with null ip.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testGetHostsByNullIp() {
+        VirtualNetwork vnet = setupVnet();
+        HostService hostService = manager.get(vnet.id(), HostService.class);
+
+        hostService.getHostsByIp(null);
+    }
+
+    /**
+     * Tests querying for connected hosts with null host location (connect point).
+     */
+    @Test(expected = NullPointerException.class)
+    public void testGetConnectedHostsByNullLoc() {
+        VirtualNetwork vnet = setupEmptyVnet();
+        HostService hostService = manager.get(vnet.id(), HostService.class);
+
+        hostService.getConnectedHosts((ConnectPoint) null);
+    }
+
+    /**
+     * Tests querying for connected hosts with null device id.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testGetConnectedHostsByNullDeviceId() {
+        VirtualNetwork vnet = setupVnet();
+        HostService hostService = manager.get(vnet.id(), HostService.class);
+
+        hostService.getConnectedHosts((DeviceId) null);
+    }
+
+}