Exposed NetworkManager interface and made it more generic to support CNI
This commit is contained in:
Родитель
a632028510
Коммит
0bf716e607
|
@ -33,28 +33,36 @@ type endpoint struct {
|
|||
IPv6Gateway net.IP
|
||||
}
|
||||
|
||||
// EndpointInfo contains read-only information about an endpoint.
|
||||
type EndpointInfo struct {
|
||||
Id string
|
||||
IfName string
|
||||
IPv4Address string
|
||||
NetNsPath string
|
||||
}
|
||||
|
||||
// NewEndpoint creates a new endpoint in the network.
|
||||
func (nw *network) newEndpoint(endpointId string, ipAddress string) (*endpoint, error) {
|
||||
func (nw *network) newEndpoint(epInfo *EndpointInfo) (*endpoint, error) {
|
||||
var containerIf *net.Interface
|
||||
var ep *endpoint
|
||||
var err error
|
||||
|
||||
if nw.Endpoints[endpointId] != nil {
|
||||
if nw.Endpoints[epInfo.Id] != nil {
|
||||
return nil, errEndpointExists
|
||||
}
|
||||
|
||||
// Parse IP address.
|
||||
ipAddr, ipNet, err := net.ParseCIDR(ipAddress)
|
||||
ipAddr, ipNet, err := net.ParseCIDR(epInfo.IPv4Address)
|
||||
ipNet.IP = ipAddr
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Printf("[net] Creating endpoint %v in network %v.", endpointId, nw.Id)
|
||||
log.Printf("[net] Creating endpoint %v in network %v.", epInfo.Id, nw.Id)
|
||||
|
||||
// Create a veth pair.
|
||||
hostIfName := fmt.Sprintf("%s%s", hostInterfacePrefix, endpointId[:7])
|
||||
contIfName := fmt.Sprintf("%s%s-2", hostInterfacePrefix, endpointId[:7])
|
||||
hostIfName := fmt.Sprintf("%s%s", hostInterfacePrefix, epInfo.Id[:7])
|
||||
contIfName := fmt.Sprintf("%s%s-2", hostInterfacePrefix, epInfo.Id[:7])
|
||||
|
||||
log.Printf("[net] Creating veth pair %v %v.", hostIfName, contIfName)
|
||||
err = netlink.AddVethPair(contIfName, hostIfName)
|
||||
|
@ -97,6 +105,31 @@ func (nw *network) newEndpoint(endpointId string, ipAddress string) (*endpoint,
|
|||
goto cleanup
|
||||
}
|
||||
|
||||
// If a name for the container interface is specified...
|
||||
if epInfo.IfName != "" {
|
||||
// Interface needs to be down before renaming.
|
||||
log.Printf("[net] Setting link %v state down.", contIfName)
|
||||
err = netlink.SetLinkState(contIfName, false)
|
||||
if err != nil {
|
||||
goto cleanup
|
||||
}
|
||||
|
||||
// Rename the container interface.
|
||||
log.Printf("[net] Setting link %v name %v.", contIfName, epInfo.IfName)
|
||||
err = netlink.SetLinkName(contIfName, epInfo.IfName)
|
||||
if err != nil {
|
||||
goto cleanup
|
||||
}
|
||||
contIfName = epInfo.IfName
|
||||
|
||||
// Bring the interface back up.
|
||||
log.Printf("[net] Setting link %v state up.", contIfName)
|
||||
err = netlink.SetLinkState(contIfName, true)
|
||||
if err != nil {
|
||||
goto cleanup
|
||||
}
|
||||
}
|
||||
|
||||
// Assign IP address to container network interface.
|
||||
log.Printf("[net] Adding IP address %v to link %v.", ipAddr, contIfName)
|
||||
err = netlink.AddIpAddress(contIfName, ipAddr, ipNet)
|
||||
|
@ -106,7 +139,7 @@ func (nw *network) newEndpoint(endpointId string, ipAddress string) (*endpoint,
|
|||
|
||||
// Create the endpoint object.
|
||||
ep = &endpoint{
|
||||
Id: endpointId,
|
||||
Id: epInfo.Id,
|
||||
SrcName: contIfName,
|
||||
DstPrefix: containerInterfacePrefix,
|
||||
MacAddress: containerIf.HardwareAddr,
|
||||
|
@ -116,7 +149,7 @@ func (nw *network) newEndpoint(endpointId string, ipAddress string) (*endpoint,
|
|||
IPv6Gateway: nw.extIf.IPv6Gateway,
|
||||
}
|
||||
|
||||
nw.Endpoints[endpointId] = ep
|
||||
nw.Endpoints[epInfo.Id] = ep
|
||||
|
||||
log.Printf("[net] Created endpoint %+v.", ep)
|
||||
|
||||
|
|
|
@ -24,12 +24,25 @@ type networkManager struct {
|
|||
}
|
||||
|
||||
// NetworkManager API.
|
||||
type NetApi interface {
|
||||
type NetworkManager interface {
|
||||
Initialize(config *common.PluginConfig) error
|
||||
Uninitialize()
|
||||
|
||||
AddExternalInterface(ifName string, subnet string) error
|
||||
|
||||
CreateNetwork(nwInfo *NetworkInfo) error
|
||||
DeleteNetwork(networkId string) error
|
||||
GetNetworkInfo(networkId string) (*NetworkInfo, error)
|
||||
|
||||
CreateEndpoint(networkId string, epInfo *EndpointInfo) error
|
||||
DeleteEndpoint(networkId string, endpointId string) error
|
||||
GetEndpointInfo(networkId string, endpointId string) (*EndpointInfo, error)
|
||||
AttachEndpoint(networkId string, endpointId string, sandboxKey string) (*endpoint, error)
|
||||
DetachEndpoint(networkId string, endpointId string) error
|
||||
}
|
||||
|
||||
// Creates a new network manager.
|
||||
func newNetworkManager() (*networkManager, error) {
|
||||
func NewNetworkManager() (NetworkManager, error) {
|
||||
nm := &networkManager{
|
||||
ExternalInterfaces: make(map[string]*externalInterface),
|
||||
}
|
||||
|
@ -122,11 +135,11 @@ func (nm *networkManager) AddExternalInterface(ifName string, subnet string) err
|
|||
}
|
||||
|
||||
// CreateNetwork creates a new container network.
|
||||
func (nm *networkManager) CreateNetwork(networkId string, options map[string]interface{}, ipv4Data, ipv6Data []ipamData) error {
|
||||
func (nm *networkManager) CreateNetwork(nwInfo *NetworkInfo) error {
|
||||
nm.Lock()
|
||||
defer nm.Unlock()
|
||||
|
||||
_, err := nm.newNetwork(networkId, options, ipv4Data, ipv6Data)
|
||||
_, err := nm.newNetwork(nwInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -157,8 +170,26 @@ func (nm *networkManager) DeleteNetwork(networkId string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetNetworkInfo returns information about the given network.
|
||||
func (nm *networkManager) GetNetworkInfo(networkId string) (*NetworkInfo, error) {
|
||||
nm.Lock()
|
||||
defer nm.Unlock()
|
||||
|
||||
nw, err := nm.getNetwork(networkId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nwInfo := &NetworkInfo{
|
||||
Id: networkId,
|
||||
Subnets: []string{nw.extIf.Subnets[0]},
|
||||
}
|
||||
|
||||
return nwInfo, nil
|
||||
}
|
||||
|
||||
// CreateEndpoint creates a new container endpoint.
|
||||
func (nm *networkManager) CreateEndpoint(networkId string, endpointId string, ipAddress string) error {
|
||||
func (nm *networkManager) CreateEndpoint(networkId string, epInfo *EndpointInfo) error {
|
||||
nm.Lock()
|
||||
defer nm.Unlock()
|
||||
|
||||
|
@ -167,7 +198,7 @@ func (nm *networkManager) CreateEndpoint(networkId string, endpointId string, ip
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = nw.newEndpoint(endpointId, ipAddress)
|
||||
_, err = nw.newEndpoint(epInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -203,6 +234,29 @@ func (nm *networkManager) DeleteEndpoint(networkId string, endpointId string) er
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetEndpointInfo returns information about the given endpoint.
|
||||
func (nm *networkManager) GetEndpointInfo(networkId string, endpointId string) (*EndpointInfo, error) {
|
||||
nm.Lock()
|
||||
defer nm.Unlock()
|
||||
|
||||
nw, err := nm.getNetwork(networkId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ep, err := nw.getEndpoint(endpointId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
epInfo := &EndpointInfo{
|
||||
Id: endpointId,
|
||||
IPv4Address: ep.IPv4Address.String(),
|
||||
}
|
||||
|
||||
return epInfo, nil
|
||||
}
|
||||
|
||||
// AttachEndpoint attaches an endpoint to a sandbox.
|
||||
func (nm *networkManager) AttachEndpoint(networkId string, endpointId string, sandboxKey string) (*endpoint, error) {
|
||||
nm.Lock()
|
||||
|
|
|
@ -38,6 +38,14 @@ type network struct {
|
|||
extIf *externalInterface
|
||||
}
|
||||
|
||||
// NetworkInfo contains read-only information about a container network.
|
||||
type NetworkInfo struct {
|
||||
Id string
|
||||
Subnets []string
|
||||
BridgeName string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
type options map[string]interface{}
|
||||
|
||||
// NewExternalInterface adds a host interface to the list of available external interfaces.
|
||||
|
@ -93,7 +101,7 @@ func (nm *networkManager) findExternalInterfaceBySubnet(subnet string) *external
|
|||
}
|
||||
|
||||
// ConnectExternalInterface connects the given host interface to a bridge.
|
||||
func (nm *networkManager) connectExternalInterface(extIf *externalInterface) error {
|
||||
func (nm *networkManager) connectExternalInterface(extIf *externalInterface, bridgeName string) error {
|
||||
var addrs []net.Addr
|
||||
|
||||
log.Printf("[net] Connecting interface %v.", extIf.Name)
|
||||
|
@ -104,7 +112,10 @@ func (nm *networkManager) connectExternalInterface(extIf *externalInterface) err
|
|||
return err
|
||||
}
|
||||
|
||||
bridgeName := fmt.Sprintf("%s%d", bridgePrefix, hostIf.Index)
|
||||
// If a bridge name is not specified, generate one based on the external interface index.
|
||||
if bridgeName == "" {
|
||||
bridgeName = fmt.Sprintf("%s%d", bridgePrefix, hostIf.Index)
|
||||
}
|
||||
|
||||
// Check if the bridge already exists.
|
||||
bridge, err := net.InterfaceByName(bridgeName)
|
||||
|
@ -287,32 +298,23 @@ func (nm *networkManager) disconnectExternalInterface(extIf *externalInterface)
|
|||
}
|
||||
|
||||
// NewNetwork creates a new container network.
|
||||
func (nm *networkManager) newNetwork(networkId string, options map[string]interface{}, ipv4Data, ipv6Data []ipamData) (*network, error) {
|
||||
// Assume single pool per address family.
|
||||
var ipv4Pool, ipv6Pool string
|
||||
if len(ipv4Data) > 0 {
|
||||
ipv4Pool = ipv4Data[0].Pool
|
||||
}
|
||||
func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) {
|
||||
|
||||
if len(ipv6Data) > 0 {
|
||||
ipv6Pool = ipv6Data[0].Pool
|
||||
}
|
||||
|
||||
log.Printf("[net] Creating network %v for subnet %v %v.", networkId, ipv4Pool, ipv6Pool)
|
||||
log.Printf("[net] Creating network %+v.", nwInfo)
|
||||
|
||||
// Find the external interface for this subnet.
|
||||
extIf := nm.findExternalInterfaceBySubnet(ipv4Pool)
|
||||
extIf := nm.findExternalInterfaceBySubnet(nwInfo.Subnets[0])
|
||||
if extIf == nil {
|
||||
return nil, fmt.Errorf("Pool not found")
|
||||
}
|
||||
|
||||
if extIf.Networks[networkId] != nil {
|
||||
if extIf.Networks[nwInfo.Id] != nil {
|
||||
return nil, errNetworkExists
|
||||
}
|
||||
|
||||
// Connect the external interface if not already connected.
|
||||
if extIf.BridgeName == "" {
|
||||
err := nm.connectExternalInterface(extIf)
|
||||
err := nm.connectExternalInterface(extIf, nwInfo.BridgeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -320,14 +322,14 @@ func (nm *networkManager) newNetwork(networkId string, options map[string]interf
|
|||
|
||||
// Create the network object.
|
||||
nw := &network{
|
||||
Id: networkId,
|
||||
Id: nwInfo.Id,
|
||||
Endpoints: make(map[string]*endpoint),
|
||||
extIf: extIf,
|
||||
}
|
||||
|
||||
extIf.Networks[networkId] = nw
|
||||
extIf.Networks[nwInfo.Id] = nw
|
||||
|
||||
log.Printf("[net] Created network %v on interface %v.", networkId, extIf.Name)
|
||||
log.Printf("[net] Created network %v on interface %v.", nwInfo.Id, extIf.Name)
|
||||
|
||||
return nw, nil
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ const (
|
|||
type netPlugin struct {
|
||||
*common.Plugin
|
||||
scope string
|
||||
nm *networkManager
|
||||
nm NetworkManager
|
||||
}
|
||||
|
||||
type NetPlugin interface {
|
||||
|
@ -38,7 +38,7 @@ func NewPlugin(config *common.PluginConfig) (NetPlugin, error) {
|
|||
}
|
||||
|
||||
// Setup network manager.
|
||||
nm, err := newNetworkManager()
|
||||
nm, err := NewNetworkManager()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -120,7 +120,21 @@ func (plugin *netPlugin) createNetwork(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Process request.
|
||||
err = plugin.nm.CreateNetwork(req.NetworkID, req.Options, req.IPv4Data, req.IPv6Data)
|
||||
nwInfo := NetworkInfo{
|
||||
Id: req.NetworkID,
|
||||
Options: req.Options,
|
||||
}
|
||||
|
||||
// Assume single pool per address family.
|
||||
if len(req.IPv4Data) > 0 {
|
||||
nwInfo.Subnets = append(nwInfo.Subnets, req.IPv4Data[0].Pool)
|
||||
}
|
||||
|
||||
if len(req.IPv6Data) > 0 {
|
||||
nwInfo.Subnets = append(nwInfo.Subnets, req.IPv6Data[0].Pool)
|
||||
}
|
||||
|
||||
err = plugin.nm.CreateNetwork(&nwInfo)
|
||||
if err != nil {
|
||||
plugin.SendErrorResponse(w, err)
|
||||
return
|
||||
|
@ -175,7 +189,12 @@ func (plugin *netPlugin) createEndpoint(w http.ResponseWriter, r *http.Request)
|
|||
ipv4Address = req.Interface.Address
|
||||
}
|
||||
|
||||
err = plugin.nm.CreateEndpoint(req.NetworkID, req.EndpointID, ipv4Address)
|
||||
epInfo := EndpointInfo{
|
||||
Id: req.EndpointID,
|
||||
IPv4Address: ipv4Address,
|
||||
}
|
||||
|
||||
err = plugin.nm.CreateEndpoint(req.NetworkID, &epInfo)
|
||||
if err != nil {
|
||||
plugin.SendErrorResponse(w, err)
|
||||
return
|
||||
|
|
Загрузка…
Ссылка в новой задаче