/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.brooklyn.location.localhost; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; import java.net.ServerSocket; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.net.Networking; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.apache.brooklyn.api.location.LocationSpec; import org.apache.brooklyn.api.location.MachineProvisioningLocation; import org.apache.brooklyn.api.location.NoMachinesAvailableException; import org.apache.brooklyn.api.location.PortRange; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.location.PortRanges; import org.apache.brooklyn.core.location.geo.HostGeoInfo; import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; import org.apache.brooklyn.location.ssh.SshMachineLocation; public class LocalhostMachineProvisioningLocationTest { private static final Logger log = LoggerFactory.getLogger(LocalhostMachineProvisioningLocationTest.class); private LocalManagementContext mgmt; @BeforeMethod @AfterClass protected void clearStatics() { LocalhostMachineProvisioningLocation.clearStaticData(); } @BeforeClass protected void setup() { mgmt = LocalManagementContextForTests.newInstance(); } @AfterClass protected void teardown() { Entities.destroyAll(mgmt); } protected LocalhostMachineProvisioningLocation newLocalhostProvisioner() { return mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); } protected LocalhostMachineProvisioningLocation newLocalhostProvisionerWithAddress(String address) { return mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class) .configure("address", address)); } @Test public void defaultInvocationCanProvisionALocalhostInstance() throws Exception { LocalhostMachineProvisioningLocation provisioner = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); SshMachineLocation machine = provisioner.obtain(); assertNotNull(machine); assertEquals(machine.getAddress(), Networking.getLocalHost()); } @Test public void testUsesLocationNameProvided() throws Exception { LocalhostMachineProvisioningLocation provisioner = newLocalhostProvisionerWithAddress("localhost"); assertEquals(((SshMachineLocation)provisioner.obtain()).getAddress().getHostName(), "localhost"); LocalhostMachineProvisioningLocation provisioner2 = newLocalhostProvisionerWithAddress("1.2.3.4"); assertEquals(((SshMachineLocation)provisioner2.obtain()).getAddress().getHostName(), "1.2.3.4"); LocalhostMachineProvisioningLocation provisioner3 = newLocalhostProvisionerWithAddress("127.0.0.1"); assertEquals(((SshMachineLocation)provisioner3.obtain()).getAddress().getHostName(), "127.0.0.1"); } public void provisionWithASpecificNumberOfInstances() throws NoMachinesAvailableException { LocalhostMachineProvisioningLocation provisioner = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class) .configure("count", 2)); // first machine SshMachineLocation first = provisioner.obtain(); assertNotNull(first); assertEquals(first.getAddress(), Networking.getLocalHost()); // second machine SshMachineLocation second = provisioner.obtain(); assertNotNull(second); assertEquals(second.getAddress(), Networking.getLocalHost()); // third machine - fails try { SshMachineLocation third = provisioner.obtain(); fail("did not throw expected exception; got "+third); } catch (NoMachinesAvailableException e) { /* expected */ } } @Test public void obtainTwoAddressesInRangeThenDontObtain() throws Exception { LocalhostMachineProvisioningLocation p = newLocalhostProvisioner(); SshMachineLocation m = p.obtain(); // Find two ports that are free, rather than risk false-negatives if a port was left open by something else. int start = 48311; while (true) { if (Networking.isPortAvailable(m.getAddress(), start) && Networking.isPortAvailable(m.getAddress(), start+1)) { break; } else { start++; } } PortRange r = PortRanges.fromString(""+start+"-"+(start+1)); try { int i1 = m.obtainPort(r); Assert.assertEquals(i1, start); int i2 = m.obtainPort(r); Assert.assertEquals(i2, start+1); //should fail int i3 = m.obtainPort(r); Assert.assertEquals(i3, -1); //releasing and reapplying should succed m.releasePort(i2); int i4 = m.obtainPort(r); Assert.assertEquals(i4, i2); } finally { m.releasePort(start); m.releasePort(start+1); } } @Test public void obtainLowNumberedPortsAutomatically() throws Exception { LocalhostMachineProvisioningLocation p = newLocalhostProvisioner(); SshMachineLocation m = p.obtain(); int start = 983; //random rarely used port, not that it matters try { int actual = m.obtainPort(PortRanges.fromInteger(start)); Assert.assertEquals(actual, start); } finally { m.releasePort(start); } } @Test public void obtainPortFailsIfInUse() throws Exception { LocalhostMachineProvisioningLocation p = newLocalhostProvisioner(); SshMachineLocation m = p.obtain(); // Find two ports that are free, rather than risk false-negatives if a port was left open by something else. int start = 48311; while (true) { if (Networking.isPortAvailable(m.getAddress(), start) && Networking.isPortAvailable(m.getAddress(), start+1)) { break; } else { start++; } } PortRange r = PortRanges.fromString(""+start+"-"+(start+1)); ServerSocket ss = null; try { ss = new ServerSocket(start, 0, m.getAddress()); int i1 = m.obtainPort(r); Assert.assertEquals(i1, start+1); } finally { if (ss!=null) ss.close(); m.releasePort(start); m.releasePort(start+1); } } @Test public void obtainLocationWithGeography() throws Exception { mgmt.getBrooklynProperties().put("brooklyn.location.named.lhx", "localhost"); // bogus location so very little chance of it being what maxmind returns! mgmt.getBrooklynProperties().put("brooklyn.location.named.lhx.latitude", 42d); mgmt.getBrooklynProperties().put("brooklyn.location.named.lhx.longitude", -20d); MachineProvisioningLocation<?> p = (MachineProvisioningLocation<?>) mgmt.getLocationRegistry().resolve("named:lhx"); SshMachineLocation m = (SshMachineLocation) p.obtain(MutableMap.of()); HostGeoInfo geo = HostGeoInfo.fromLocation(m); log.info("Geo info for "+m+" is: "+geo); Assert.assertEquals(geo.latitude, 42d, 0.00001); Assert.assertEquals(geo.longitude, -20d, 0.00001); } }