added raft over tls
This commit is contained in:
parent
b0d13076e0
commit
585baea183
16 changed files with 563 additions and 300 deletions
|
|
@ -5,6 +5,6 @@ package vip
|
|||
import "fmt"
|
||||
|
||||
// ARPSendGratuitous is only supported on Linux, so return an error
|
||||
func ARPSendGratuitous(address, ifaceName string) error {
|
||||
func ARPSendGratuitous(cidr, iface string) error {
|
||||
return fmt.Errorf("Unsupported on this OS")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ import (
|
|||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -156,21 +154,20 @@ func sendARP(iface *net.Interface, m *arpMessage) error {
|
|||
}
|
||||
|
||||
// ARPSendGratuitous sends a gratuitous ARP message via the specified interface.
|
||||
func ARPSendGratuitous(address, ifaceName string) error {
|
||||
iface, err := net.InterfaceByName(ifaceName)
|
||||
func ARPSendGratuitous(cidr, iface string) error {
|
||||
i, err := net.InterfaceByName(iface)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get interface %q: %v", ifaceName, err)
|
||||
return fmt.Errorf("failed to get interface %q: %v", iface, err)
|
||||
}
|
||||
ip, _, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse cidr: %s", cidr)
|
||||
}
|
||||
|
||||
ip := net.ParseIP(address)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("failed to parse address %s", ip)
|
||||
}
|
||||
|
||||
log.Infof("Broadcasting ARP update for %s (%s) via %s", address, iface.HardwareAddr, iface.Name)
|
||||
m, err := gratuitousARP(ip, iface.HardwareAddr)
|
||||
//log.Infof("Broadcasting ARP update for %s (%s) via %s", address, iface.HardwareAddr, iface.Name)
|
||||
m, err := gratuitousARP(ip, i.HardwareAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sendARP(iface, m)
|
||||
return sendARP(i, m)
|
||||
}
|
||||
|
|
|
|||
195
pkg/vip/vip.go
195
pkg/vip/vip.go
|
|
@ -1,142 +1,97 @@
|
|||
package vip
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"github.com/vishvananda/netlink"
|
||||
"net"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultValidLft = 60
|
||||
)
|
||||
var ErrNoDefaultInterface = errors.New("no default interface found")
|
||||
|
||||
// Network is an interface that enable managing operations for a given IP
|
||||
type Network interface {
|
||||
AddIP() error
|
||||
DeleteIP() error
|
||||
IsSet() (bool, error)
|
||||
IP() string
|
||||
SetIP(ip string) error
|
||||
Interface() string
|
||||
}
|
||||
|
||||
// network - This allows network configuration
|
||||
type network struct {
|
||||
mu sync.Mutex
|
||||
|
||||
address *netlink.Addr
|
||||
link netlink.Link
|
||||
isDNS bool
|
||||
}
|
||||
|
||||
// NewConfig will attempt to provide an interface to the kernel network configuration
|
||||
func NewConfig(address string, iface string) (Network, error) {
|
||||
result := &network{}
|
||||
|
||||
link, err := netlink.LinkByName(iface)
|
||||
func DefaultInterface() (iface string, err error) {
|
||||
routes, err := netlink.RouteGet(net.IPv4bcast)
|
||||
if err != nil {
|
||||
return result, errors.Wrapf(err, "could not get link for interface '%s'", iface)
|
||||
}
|
||||
result.link = link
|
||||
|
||||
if IsIP(address) {
|
||||
result.address, err = netlink.ParseAddr(address + "/32")
|
||||
if err != nil {
|
||||
return result, errors.Wrapf(err, "could not parse address '%s'", address)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// try to resolve the address
|
||||
ip, err := lookupHost(address)
|
||||
result.isDNS = err == nil
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// we're able to resolve store this as the initial IP
|
||||
if result.address, err = netlink.ParseAddr(ip + "/32"); err != nil {
|
||||
return result, err
|
||||
}
|
||||
// set ValidLft so that the VIP expires if the DNS entry is updated, otherwise it'll be refreshed by the DNS prober
|
||||
result.address.ValidLft = defaultValidLft
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
//AddIP - Add an IP address to the interface
|
||||
func (configurator *network) AddIP() error {
|
||||
if err := netlink.AddrReplace(configurator.link, configurator.address); err != nil {
|
||||
return errors.Wrap(err, "could not add ip")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//DeleteIP - Remove an IP address from the interface
|
||||
func (configurator *network) DeleteIP() error {
|
||||
result, err := configurator.IsSet()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ip check in DeleteIP failed")
|
||||
}
|
||||
|
||||
// Nothing to delete
|
||||
if !result {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = netlink.AddrDel(configurator.link, configurator.address); err != nil {
|
||||
return errors.Wrap(err, "could not delete ip")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsSet - Check to see if VIP is set
|
||||
func (configurator *network) IsSet() (result bool, err error) {
|
||||
var addresses []netlink.Addr
|
||||
|
||||
addresses, err = netlink.AddrList(configurator.link, 0)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "could not list addresses")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, address := range addresses {
|
||||
if address.Equal(*configurator.address) {
|
||||
return true, nil
|
||||
if len(routes) >= 1 {
|
||||
link, e := netlink.LinkByIndex(routes[0].LinkIndex)
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
}
|
||||
return link.Attrs().Name, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
err = ErrNoDefaultInterface
|
||||
return
|
||||
}
|
||||
|
||||
// SetIP updates the IP that is used
|
||||
func (configurator *network) SetIP(ip string) error {
|
||||
configurator.mu.Lock()
|
||||
defer configurator.mu.Unlock()
|
||||
type Network struct {
|
||||
iface string
|
||||
label string
|
||||
link netlink.Link
|
||||
}
|
||||
|
||||
addr, err := netlink.ParseAddr(ip + "/32")
|
||||
func NewNetwork(iface string) (n *Network, err error) {
|
||||
return NewNetworkWithLabel(iface, "")
|
||||
}
|
||||
|
||||
func NewNetworkWithLabel(iface, label string) (n *Network, err error) {
|
||||
if iface == "" {
|
||||
iface, err = DefaultInterface()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
link, err := netlink.LinkByName(iface)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n = &Network{iface, label, link}
|
||||
return
|
||||
}
|
||||
|
||||
func (n *Network) Interface() string {
|
||||
return n.iface
|
||||
}
|
||||
|
||||
func (n *Network) HasIP(a *netlink.Addr) bool {
|
||||
addrs, err := netlink.AddrList(n.link, 0)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
if addr.Equal(*a) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *Network) AddIP(cidr string) error {
|
||||
addr, err := netlink.ParseAddr(cidr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if configurator.address != nil && configurator.isDNS {
|
||||
addr.ValidLft = defaultValidLft
|
||||
if n.HasIP(addr) {
|
||||
return nil
|
||||
}
|
||||
configurator.address = addr
|
||||
return nil
|
||||
if n.label != "" {
|
||||
addr.Label = n.iface + ":" + n.label
|
||||
}
|
||||
err = netlink.AddrReplace(n.link, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ARPSendGratuitous(cidr, n.iface)
|
||||
}
|
||||
|
||||
// IP - return the IP Address
|
||||
func (configurator *network) IP() string {
|
||||
configurator.mu.Lock()
|
||||
defer configurator.mu.Unlock()
|
||||
|
||||
return configurator.address.IP.String()
|
||||
}
|
||||
|
||||
// Interface - return the Interface name
|
||||
func (configurator *network) Interface() string {
|
||||
return configurator.link.Attrs().Name
|
||||
func (n *Network) DeleteIP(cidr string) error {
|
||||
addr, err := netlink.ParseAddr(cidr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !n.HasIP(addr) {
|
||||
return nil
|
||||
}
|
||||
return netlink.AddrDel(n.link, addr)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue