Skip to content

Commit

Permalink
Merge pull request #1 from yuewko/v.0.0
Browse files Browse the repository at this point in the history
V.0.0
  • Loading branch information
johnbelamaric authored Jun 18, 2016
2 parents 4d964d1 + e0a58a8 commit 585f58c
Show file tree
Hide file tree
Showing 16 changed files with 924 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM ubuntu

ADD infoblox-daemon /usr/local/bin/infoblox-daemon


ENTRYPOINT ["/usr/local/bin/infoblox-daemon"]
59 changes: 59 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
COMMON_SOURCES=config.go driver-socket.go cmdargs.go
PLUGIN_SOURCES=plugin.go $(COMMON_SOURCES)
DAEMON_SOURCES=daemon.go infoblox-ipam.go $(COMMON_SOURCES)
PLUGIN_BINARY=infoblox-plugin
DAEMON_BINARY=infoblox-daemon
ALL_BINARIES=$(PLUGIN_BINARY) $(DAEMON_BINARY)

DAEMON_ACI_IMAGE=infoblox-cni-daemon.aci
DAEMON_DOCKER_IMAGE=infoblox-cni-daemon
DEV_IMAGE=$(DOCKERHUB_ID)/$(DAEMON_DOCKER_IMAGE) # Requires DOCKERHUB_ID environment variable
RELEASE_IMAGE=infoblox/$(DAEMON_DOCKER_IMAGE)


# Build binary
all: build

# Build binary - this is the default target
build: $(ALL_BINARIES)

$(PLUGIN_BINARY): $(PLUGIN_SOURCES)
go build -o $(PLUGIN_BINARY) $(PLUGIN_SOURCES)

$(DAEMON_BINARY): $(DAEMON_SOURCES)
go build -o $(DAEMON_BINARY) $(DAEMON_SOURCES)

# Delete binary for clean build
clean:
rm -f $(ALL_BINARIES)


# Container Images...

images: aci-image docker-image

docker-image: $(DAEMON_BINARY)
docker build -t $(DAEMON_DOCKER_IMAGE) .

# Push image to user's docker hub. NOTE: requires DOCKERHUB_ID environment variable
push: docker-image
docker tag $(DAEMON_DOCKER_IMAGE) $(DEV_IMAGE)
docker push $(DEV_IMAGE)

# Push image to infoblox docker hub
push-release: docker-image
docker tag $(DAEMON_DOCKER_IMAGE) $(RELEASE_IMAGE)
docker push $(RELEASE_IMAGE)

aci-image: $(DAEMON_ACI_IMAGE)

$(DAEMON_ACI_IMAGE): $(DAEMON_BINARY)
./build-aci.sh

# Clean everything
clean-all: clean clean-images

# Delete local docker images
clean-images:
docker rmi -f $(DAEMON_DOCKER_IMAGE)
/bin/rm -f $(DAEMON_ACI_IMAGE)
19 changes: 19 additions & 0 deletions build-aci.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

# Build ACI image for infoblox-daemon

acbuild begin

acbuild set-name infoblox.com/cni-infoblox-daemon

acbuild dependency add quay.io/quay/ubuntu:latest

acbuild mount add run-cni /run/cni

acbuild copy infoblox-daemon /usr/local/bin/infoblox-daemon

acbuild set-exec /usr/local/bin/infoblox-daemon

acbuild write --overwrite infoblox-cni-daemon.aci

acbuild end
27 changes: 27 additions & 0 deletions cmdargs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2016 Infoblox Inc.
// All Rights Reserved.
//
// 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 main

import (
"github.com/containernetworking/cni/pkg/skel"
)

// Extend skel.CmdArgs to include IfMac
// IfMac is set in the plugin and sent to the daemon
type ExtCmdArgs struct {
skel.CmdArgs
IfMac string
}
95 changes: 95 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2016 Infoblox Inc.
// All Rights Reserved.
//
// 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 main

import (
"flag"
"net"

"github.com/containernetworking/cni/pkg/types"
)

const (
HTTP_REQUEST_TIMEOUT = 60
HTTP_POOL_CONNECTIONS = 10
)

type GridConfig struct {
GridHost string
WapiVer string
WapiPort string
WapiUsername string
WapiPassword string
SslVerify string
HttpRequestTimeout int
HttpPoolConnections int
HttpPoolMaxSize int
}

type DriverConfig struct {
SocketDir string
DriverName string
NetworkView string
NetworkContainer string
PrefixLength uint
}

type Config struct {
GridConfig
DriverConfig
}

func LoadConfig() (config *Config) {
config = new(Config)

flag.StringVar(&config.GridHost, "grid-host", "192.168.124.200", "IP of Infoblox Grid Host")
flag.StringVar(&config.WapiVer, "wapi-version", "2.0", "Infoblox WAPI Version.")
flag.StringVar(&config.WapiPort, "wapi-port", "443", "Infoblox WAPI Port.")
flag.StringVar(&config.WapiUsername, "wapi-username", "", "Infoblox WAPI Username")
flag.StringVar(&config.WapiPassword, "wapi-password", "", "Infoblox WAPI Password")
flag.StringVar(&config.SslVerify, "ssl-verify", "false", "Specifies whether (true/false) to verify server certificate. If a file path is specified, it is assumed to be a certificate file and will be used to verify server certificate.")
flag.StringVar(&config.NetworkView, "network-view", "default", "Infoblox Network View")
flag.StringVar(&config.NetworkContainer, "network-container", "172.18.0.0/16", "Subnets will be allocated from this container if subnet is not specified in IPAM config")
flag.UintVar(&config.PrefixLength, "prefix-length", 24, "The default CIDR prefix length when allocating a subnet from Network Container")
config.HttpRequestTimeout = HTTP_REQUEST_TIMEOUT
config.HttpPoolConnections = HTTP_POOL_CONNECTIONS

flag.StringVar(&config.SocketDir, "socket-dir", GetDefaultSocketDir(), "Directory where Infoblox IPAM daemon sockets are created")
flag.StringVar(&config.DriverName, "driver-name", "infoblox", "Name of Infoblox IPAM driver")

flag.Parse()

return config
}

type IPAMConfig struct {
Type string `json:"type"`
SocketDir string `json:"socket-dir"`
NetworkView string `json:"network-view"`
NetworkContainer string `json:"network-container"`
PrefixLength uint `json:"prefix-length"`
Subnet types.IPNet `json:"subnet"`
Gateway net.IP `json:"gateway"`
Routes []types.Route `json:"routes"`
}

type NetConfig struct {
Name string `json:"name"`
Type string `json:"type"`
Bridge string `json:"bridge"`
IsGateway bool `json:"isGateway"`
IPAM *IPAMConfig `json:"ipam"`
}
138 changes: 138 additions & 0 deletions daemon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright 2016 Infoblox Inc.
// All Rights Reserved.
//
// 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 main

import (
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"net/rpc"
"runtime"

"github.com/containernetworking/cni/pkg/types"
ibclient "github.com/infobloxopen/infoblox-go-client"
)

type Infoblox struct {
Drv *InfobloxDriver
}

func newInfoblox(drv *InfobloxDriver) *Infoblox {
return &Infoblox{
Drv: drv,
}
}

// Allocate acquires an IP from Infoblox for a specified container.
func (ib *Infoblox) Allocate(args *ExtCmdArgs, result *types.Result) (err error) {
conf := NetConfig{}
if err = json.Unmarshal(args.StdinData, &conf); err != nil {
return fmt.Errorf("error parsing netconf: %v", err)
}

cidr := net.IPNet{IP: conf.IPAM.Subnet.IP, Mask: conf.IPAM.Subnet.Mask}
netviewName := conf.IPAM.NetworkView
if netviewName == "" {
netviewName = ib.Drv.networkView
}
log.Printf("RequestNetwork: '%s', '%s'", netviewName, cidr.String())
netview, _ := ib.Drv.RequestNetworkView(netviewName)
if netview == "" {
return nil
}

subnet, _ := ib.Drv.RequestNetwork(conf)
if subnet == "" {
return nil
}

mac := args.IfMac

log.Printf("RequestAddress: '%s', '%s', '%s'", netviewName, subnet, mac)
ip, _ := ib.Drv.RequestAddress(netviewName, subnet, "", mac, args.ContainerID)

ipn, _ := types.ParseCIDR(subnet)
ipn.IP = net.ParseIP(ip)
result.IP4 = &types.IPConfig{
IP: *ipn,
Gateway: conf.IPAM.Gateway,
Routes: conf.IPAM.Routes,
}

log.Printf("Allocate result: '%s'", result)
return nil
}

func (ib *Infoblox) Release(args *ExtCmdArgs, reply *struct{}) error {
conf := NetConfig{}
log.Printf("Release: called with args '%v'", *args)
if err := json.Unmarshal(args.StdinData, &conf); err != nil {
return fmt.Errorf("error parsing netconf: %v", err)
}

ref, err := ib.Drv.ReleaseAddress(conf.IPAM.NetworkView, "", args.IfMac)
log.Printf("IP Address released: '%s'", ref)

return err
}

func getListener(driverSocket *DriverSocket) (net.Listener, error) {
socketFile := driverSocket.SetupSocket()

return net.Listen("unix", socketFile)
}

func runDaemon(config *Config) {
// since other goroutines (on separate threads) will change namespaces,
// ensure the RPC server does not get scheduled onto those
runtime.LockOSThread()

log.Printf("Config is '%v'\n", *config)

conn, err := ibclient.NewConnector(
config.GridHost,
config.WapiVer,
config.WapiPort,
config.WapiUsername,
config.WapiPassword,
config.SslVerify,
config.HttpRequestTimeout,
config.HttpPoolConnections)

driverSocket := NewDriverSocket(config.SocketDir, config.DriverName)
l, err := getListener(driverSocket)

objMgr := ibclient.NewObjectManager(conn, "Rkt", "RktEngineID")

ibDrv := NewInfobloxDriver(objMgr, config.NetworkView, config.NetworkContainer, config.PrefixLength)

if err != nil {
log.Printf("Error getting listener: %v", err)
return
}

ib := newInfoblox(ibDrv)
rpc.Register(ib)
rpc.HandleHTTP()
http.Serve(l, nil)
}

func main() {
config := LoadConfig()
runDaemon(config)
}
Loading

0 comments on commit 585f58c

Please sign in to comment.