github.com/geofffranks/garden-linux@v0.0.0-20160715111146-26c893169cfa/network/bridgemgr/mgr.go (about) 1 package bridgemgr 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "strings" 8 "sync" 9 10 "code.cloudfoundry.org/garden-linux/network/subnets" 11 ) 12 13 type Builder interface { 14 Create(name string, ip net.IP, subnet *net.IPNet) (intf *net.Interface, err error) 15 Destroy(name string) error 16 } 17 18 type Lister interface { 19 List() ([]string, error) 20 } 21 22 //go:generate counterfeiter -o fake_bridge_manager/FakeBridgeManager.go . BridgeManager 23 type BridgeManager interface { 24 // Reserve reserves a bridge name for a subnet. 25 // if this is the first call of 'reserve' for a subnet created a new, unique bridge name 26 Reserve(subnet *net.IPNet, containerId string) (string, error) 27 28 // Rereserves adds a container to the list of reservations for a particular bridge name. 29 Rereserve(bridgeName string, subnet *net.IPNet, containerId string) error 30 31 // Release releases a reservation made by a particular container. 32 // If this is the last reservation, the passed destroyers Destroy method is called. 33 Release(bridgeName string, containerId string) error 34 35 // Prune deletes all bridges starting with prefix, that are unknown. 36 Prune() error 37 } 38 39 type mgr struct { 40 prefix string 41 names BridgeNameGenerator 42 builder Builder 43 lister Lister 44 45 mu sync.Mutex 46 owners map[string][]string // bridgeName -> []containerId 47 bridgeSubnet map[string]string // bridgeName -> subnet 48 subnetBridge map[string]string // subnet -> bridgeName 49 } 50 51 func New(prefix string, builder Builder, lister Lister) BridgeManager { 52 return &mgr{ 53 prefix: prefix, 54 names: NewBridgeNameGenerator(prefix), 55 builder: builder, 56 lister: lister, 57 58 owners: make(map[string][]string), 59 bridgeSubnet: make(map[string]string), 60 subnetBridge: make(map[string]string), 61 } 62 } 63 64 func (m *mgr) Reserve(subnet *net.IPNet, containerId string) (string, error) { 65 m.mu.Lock() 66 defer m.mu.Unlock() 67 68 name, present := m.subnetBridge[subnet.String()] 69 70 if !present { 71 name = m.names.Generate() 72 if _, err := m.builder.Create(name, subnets.GatewayIP(subnet), subnet); err != nil { 73 return "", err 74 } 75 m.subnetBridge[subnet.String()] = name 76 m.bridgeSubnet[name] = subnet.String() 77 } 78 79 m.owners[name] = append(m.owners[name], containerId) 80 81 return name, nil 82 } 83 84 func (m *mgr) Release(bridgeName string, containerId string) error { 85 m.mu.Lock() 86 m.owners[bridgeName] = remove(m.owners[bridgeName], containerId) 87 88 shouldDelete := false 89 if len(m.owners[bridgeName]) == 0 { 90 delete(m.owners, bridgeName) 91 delete(m.subnetBridge, m.bridgeSubnet[bridgeName]) 92 delete(m.bridgeSubnet, bridgeName) 93 shouldDelete = true 94 } 95 96 m.mu.Unlock() 97 98 if shouldDelete { 99 return m.builder.Destroy(bridgeName) 100 } 101 102 return nil 103 } 104 105 func (m *mgr) Rereserve(bridgeName string, subnet *net.IPNet, containerId string) error { 106 m.mu.Lock() 107 defer m.mu.Unlock() 108 109 if bridgeName == "" { 110 return errors.New("bridgemgr: re-reserving bridge: bridge name must not be empty") 111 } 112 113 if sn, present := m.bridgeSubnet[bridgeName]; present && sn != subnet.String() { 114 return fmt.Errorf("bridgemgr: reacquired bridge name '%s' has already been acquired for subnet %s", bridgeName, sn) 115 } 116 117 m.subnetBridge[subnet.String()] = bridgeName 118 m.owners[bridgeName] = append(m.owners[bridgeName], containerId) 119 m.bridgeSubnet[bridgeName] = subnet.String() 120 121 return nil 122 } 123 124 func (m *mgr) Prune() error { 125 list, err := m.lister.List() 126 if err != nil { 127 return fmt.Errorf("bridgemgr: pruning bridges: %v", err) 128 } 129 130 for _, b := range list { 131 if !strings.HasPrefix(b, m.prefix) { 132 continue 133 } 134 135 if !m.isReserved(b) { 136 m.builder.Destroy(b) 137 } 138 } 139 140 return nil 141 } 142 143 func (m *mgr) isReserved(r string) bool { 144 _, ok := m.bridgeSubnet[r] 145 return ok 146 } 147 148 func remove(a []string, b string) []string { 149 for i, j := range a { 150 if j == b { 151 return append(a[:i], a[i+1:]...) 152 } 153 } 154 155 return a 156 }