All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brooklyn.networking.sdn.SdnAgentImpl Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/*
 * 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()));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy