brooklyn.networking.sdn.SdnAgentImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of brooklyn-clocker-docker Show documentation
Show all versions of brooklyn-clocker-docker Show documentation
Clocker Brooklyn entities and locations for Docker integration.
/*
* Copyright 2014-2015 by Cloudsoft Corporation Limited
*
* 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 brooklyn.networking.sdn;
import java.net.InetAddress;
import java.util.Collections;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.render.RendererHints;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.DelegateEntity;
import brooklyn.entity.basic.DynamicGroup;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityLocal;
import brooklyn.entity.basic.EntityPredicates;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.entity.container.docker.DockerHost;
import brooklyn.entity.container.docker.DockerInfrastructure;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.event.feed.ConfigToAttributes;
import brooklyn.management.Task;
import brooklyn.networking.VirtualNetwork;
import brooklyn.util.net.Cidr;
import brooklyn.util.repeat.Repeater;
import brooklyn.util.task.DynamicTasks;
import brooklyn.util.task.TaskBuilder;
import brooklyn.util.time.Duration;
import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
/**
* An SDN agent process on a Docker host.
*/
public abstract class SdnAgentImpl extends SoftwareProcessImpl implements SdnAgent {
private static final Logger LOG = LoggerFactory.getLogger(SdnAgent.class);
@Override
public void init() {
super.init();
ConfigToAttributes.apply(this, DOCKER_HOST);
ConfigToAttributes.apply(this, SDN_PROVIDER);
}
@Override
public SdnAgentDriver getDriver() {
return (SdnAgentDriver) super.getDriver();
}
@Override
protected void connectSensors() {
super.connectSensors();
super.connectServiceUpIsRunning();
}
@Override
public void disconnectSensors() {
super.disconnectServiceUpIsRunning();
super.disconnectSensors();
}
@Override
public DockerHost getDockerHost() {
return getAttribute(DOCKER_HOST);
}
@Override
public void preStart() {
InetAddress address = getAttribute(SDN_PROVIDER).getNextAgentAddress(getId());
setAttribute(SDN_AGENT_ADDRESS, address);
}
@Override
public void postStart() {
((EntityLocal) getDockerHost()).setAttribute(SDN_AGENT, this);
}
@Override
public void rebind() {
super.rebind();
// TODO implement custom SDN agent rebind logic
}
@Override
public InetAddress attachNetwork(String containerId, final String networkId) {
final SdnProvider provider = getAttribute(SDN_PROVIDER);
boolean createNetwork = false;
Cidr subnetCidr = null;
synchronized (provider.getNetworkMutex()) {
subnetCidr = provider.getSubnetCidr(networkId);
if (subnetCidr == null) {
subnetCidr = provider.getNextSubnetCidr(networkId);
createNetwork = true;
}
}
if (createNetwork) {
// Get a CIDR for the subnet from the availabkle pool and create a virtual network
EntitySpec networkSpec = EntitySpec.create(VirtualNetwork.class)
.configure(VirtualNetwork.NETWORK_ID, networkId)
.configure(VirtualNetwork.NETWORK_CIDR, subnetCidr);
// Start and then add this virtual network as a child of SDN_NETWORKS
VirtualNetwork network = provider.getAttribute(SdnProvider.SDN_NETWORKS).addChild(networkSpec);
Entities.manage(network);
Entities.start(network, Collections.singleton(((DockerInfrastructure) provider.getAttribute(SdnProvider.DOCKER_INFRASTRUCTURE)).getDynamicLocation()));
Entities.waitForServiceUp(network);
} else {
Task lookup = TaskBuilder. builder()
.name("Waiting until virtual network is available")
.body(new Callable() {
@Override
public Boolean call() throws Exception {
return Repeater.create()
.every(Duration.TEN_SECONDS)
.until(new Callable() {
public Boolean call() {
Optional found = Iterables.tryFind(provider.getAttribute(SdnProvider.SDN_NETWORKS).getMembers(),
EntityPredicates.attributeEqualTo(VirtualNetwork.NETWORK_ID, networkId));
return found.isPresent();
}
})
.limitTimeTo(Duration.ONE_MINUTE)
.run();
}
})
.build();
Boolean result = DynamicTasks.queueIfPossible(lookup)
.orSubmitAndBlock()
.andWaitForSuccess();
if (!result) {
throw new IllegalStateException(String.format("Cannot find virtual network entity for %s", networkId));
}
}
InetAddress address = getDriver().attachNetwork(containerId, networkId);
LOG.info("Attached container ID {} to {}: {}", new Object[] { containerId, networkId, address.getHostAddress() });
// Rescan SDN network groups for containers
DynamicGroup network = (DynamicGroup) Iterables.find(provider.getAttribute(SdnProvider.SDN_APPLICATIONS).getMembers(),
EntityPredicates.attributeEqualTo(VirtualNetwork.NETWORK_ID, networkId));
network.rescanEntities();
return address;
}
@Override
public String provisionNetwork(VirtualNetwork network) {
String networkId = network.getAttribute(VirtualNetwork.NETWORK_ID);
// Record the network CIDR being provisioned, allocating if required
Cidr subnetCidr = network.config().get(VirtualNetwork.NETWORK_CIDR);
if (subnetCidr == null) {
subnetCidr = getAttribute(SDN_PROVIDER).getNextSubnetCidr(networkId);
} else {
getAttribute(SDN_PROVIDER).recordSubnetCidr(networkId, subnetCidr);
}
((EntityLocal) network).setAttribute(VirtualNetwork.NETWORK_CIDR, subnetCidr);
// Create the netwoek using the SDN driver
getDriver().createSubnet(network.getId(), networkId, subnetCidr);
return networkId;
}
static {
RendererHints.register(DOCKER_HOST, new RendererHints.NamedActionWithUrl("Open", DelegateEntity.EntityUrl.entityUrl()));
RendererHints.register(SDN_PROVIDER, new RendererHints.NamedActionWithUrl("Open", DelegateEntity.EntityUrl.entityUrl()));
RendererHints.register(SDN_AGENT, new RendererHints.NamedActionWithUrl("Open", DelegateEntity.EntityUrl.entityUrl()));
}
}