44package ipam
55
66import (
7+ "encoding/json"
78 "net"
89
910 "github.com/Azure/azure-container-networking/cni"
@@ -23,6 +24,15 @@ const (
2324 defaultAddressSpaceId = "LocalDefaultAddressSpace"
2425)
2526
27+ var (
28+ // Azure VNET pre-allocated host IDs.
29+ ipv4DefaultGatewayHostId = net .ParseIP ("::1" )
30+ ipv4DnsPrimaryHostId = net .ParseIP ("::2" )
31+ ipv4DnsSecondaryHostId = net .ParseIP ("::3" )
32+
33+ ipv4DefaultRouteDstPrefix = net.IPNet {net .IPv4zero , net .IPv4Mask (0 , 0 , 0 , 0 )}
34+ )
35+
2636// IpamPlugin represents a CNI IPAM plugin.
2737type ipamPlugin struct {
2838 * common.Plugin
@@ -43,31 +53,34 @@ func NewPlugin(config *common.PluginConfig) (*ipamPlugin, error) {
4353 return nil , err
4454 }
4555
46- config .IpamApi = am
47-
48- return & ipamPlugin {
56+ // Create IPAM plugin.
57+ ipamPlg := & ipamPlugin {
4958 Plugin : plugin ,
5059 am : am ,
51- }, nil
60+ }
61+
62+ config .IpamApi = ipamPlg
63+
64+ return ipamPlg , nil
5265}
5366
5467// Starts the plugin.
5568func (plugin * ipamPlugin ) Start (config * common.PluginConfig ) error {
5669 // Initialize base plugin.
5770 err := plugin .Initialize (config )
5871 if err != nil {
59- log .Printf ("[ipam] Failed to initialize base plugin, err:%v." , err )
72+ log .Printf ("[cni- ipam] Failed to initialize base plugin, err:%v." , err )
6073 return err
6174 }
6275
6376 // Initialize address manager.
6477 err = plugin .am .Initialize (config , plugin .Options )
6578 if err != nil {
66- log .Printf ("[ipam] Failed to initialize address manager, err:%v." , err )
79+ log .Printf ("[cni- ipam] Failed to initialize address manager, err:%v." , err )
6780 return err
6881 }
6982
70- log .Printf ("[ipam] Plugin started." )
83+ log .Printf ("[cni- ipam] Plugin started." )
7184
7285 return nil
7386}
@@ -76,7 +89,7 @@ func (plugin *ipamPlugin) Start(config *common.PluginConfig) error {
7689func (plugin * ipamPlugin ) Stop () {
7790 plugin .am .Uninitialize ()
7891 plugin .Uninitialize ()
79- log .Printf ("[ipam] Plugin stopped." )
92+ log .Printf ("[cni- ipam] Plugin stopped." )
8093}
8194
8295//
@@ -86,77 +99,125 @@ func (plugin *ipamPlugin) Stop() {
8699
87100// Add handles CNI add commands.
88101func (plugin * ipamPlugin ) Add (args * cniSkel.CmdArgs ) error {
89- log .Printf ("[ipam] Processing ADD command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}." ,
102+ log .Printf ("[cni- ipam] Processing ADD command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}." ,
90103 args .ContainerID , args .Netns , args .IfName , args .Args , args .Path )
91104
92105 // Parse network configuration from stdin.
93106 nwCfg , err := cni .ParseNetworkConfig (args .StdinData )
94107 if err != nil {
95- log .Printf ("[ipam] Failed to parse network configuration: %v." , err )
108+ log .Printf ("[cni- ipam] Failed to parse network configuration: %v." , err )
96109 return nil
97110 }
98111
99- log .Printf ("[ipam] Read network configuration %+v." , nwCfg )
112+ log .Printf ("[cni- ipam] Read network configuration %+v." , nwCfg )
100113
101114 // Assume default address space if not specified.
102115 if nwCfg .Ipam .AddrSpace == "" {
103116 nwCfg .Ipam .AddrSpace = defaultAddressSpaceId
104117 }
105118
119+ var poolId string
120+ var subnet string
121+ var ipv4Address * net.IPNet
122+ var result * cniTypes.Result
123+ var apInfo * ipam.AddressPoolInfo
124+
106125 // Check if an address pool is specified.
107126 if nwCfg .Ipam .Subnet == "" {
108127 // Allocate an address pool.
109- poolId , subnet , err : = plugin .am .RequestPool (nwCfg .Ipam .AddrSpace , "" , "" , nil , false )
128+ poolId , subnet , err = plugin .am .RequestPool (nwCfg .Ipam .AddrSpace , "" , "" , nil , false )
110129 if err != nil {
111- log .Printf ("[ipam] Failed to allocate pool, err:%v." , err )
130+ log .Printf ("[cni- ipam] Failed to allocate pool, err:%v." , err )
112131 return nil
113132 }
114133
115134 nwCfg .Ipam .Subnet = subnet
116- log .Printf ("[ipam] Allocated address poolId %v with subnet %v." , poolId , subnet )
135+ log .Printf ("[cni- ipam] Allocated address poolId %v with subnet %v." , poolId , subnet )
117136 }
118137
119138 // Allocate an address for the endpoint.
120139 address , err := plugin .am .RequestAddress (nwCfg .Ipam .AddrSpace , nwCfg .Ipam .Subnet , nwCfg .Ipam .Address , nil )
121140 if err != nil {
122- log .Printf ("[ipam] Failed to allocate address, err:%v." , err )
123- return nil
141+ log .Printf ("[cni- ipam] Failed to allocate address, err:%v." , err )
142+ goto Rollback
124143 }
125144
126- log .Printf ("[ipam] Allocated address %v." , address )
145+ log .Printf ("[cni- ipam] Allocated address %v." , address )
127146
128- // Output the result.
129- ip , cidr , err := net .ParseCIDR (address )
130- cidr .IP = ip
147+ // Parse IP address.
148+ ipv4Address , err = ipam .ConvertAddressToIPNet (address )
131149 if err != nil {
132- log .Printf ("[ipam] Failed to parse address, err:%v." , err )
133- return nil
150+ goto Rollback
151+ }
152+
153+ // Query pool information for gateways and DNS servers.
154+ apInfo , err = plugin .am .GetPoolInfo (nwCfg .Ipam .AddrSpace , nwCfg .Ipam .Subnet )
155+ if err != nil {
156+ goto Rollback
134157 }
135158
136- result := & cniTypes.Result {
137- IP4 : & cniTypes.IPConfig {IP : * cidr },
159+ // Populate IP configuration.
160+ result = & cniTypes.Result {
161+ IP4 : & cniTypes.IPConfig {
162+ IP : * ipv4Address ,
163+ Gateway : apInfo .Gateway ,
164+ Routes : []cniTypes.Route {
165+ cniTypes.Route {
166+ Dst : ipv4DefaultRouteDstPrefix ,
167+ GW : apInfo .Gateway ,
168+ },
169+ },
170+ },
138171 }
139172
140- result .Print ()
173+ // Populate DNS servers.
174+ for _ , ip := range apInfo .DnsServers {
175+ result .DNS .Nameservers = append (result .DNS .Nameservers , ip .String ())
176+ }
177+
178+ // Output the result.
179+ if nwCfg .Ipam .Type == cni .Internal {
180+ // Called via the internal interface. Pass output back in args.
181+ args .StdinData , _ = json .Marshal (result )
182+ } else {
183+ // Called via the executable interface. Print output to stdout.
184+ result .Print ()
185+ }
186+
187+ log .Printf ("[cni-ipam] ADD succeeded with output %+v." , result )
188+
189+ return nil
190+
191+ Rollback:
192+ // Roll back allocations made during this call.
193+ log .Printf ("[cni-ipam] ADD failed, err:%v." , err )
141194
142- log .Printf ("[ipam] ADD succeeded with output %+v." , result )
195+ if address != "" {
196+ log .Printf ("[cni-ipam] Releasing address %v." , address )
197+ err = plugin .am .ReleaseAddress (nwCfg .Ipam .AddrSpace , nwCfg .Ipam .Subnet , address )
198+ }
199+
200+ if poolId != "" {
201+ log .Printf ("[cni-ipam] Releasing pool %v." , poolId )
202+ err = plugin .am .ReleasePool (nwCfg .Ipam .AddrSpace , poolId )
203+ }
143204
144205 return err
145206}
146207
147208// Delete handles CNI delete commands.
148209func (plugin * ipamPlugin ) Delete (args * cniSkel.CmdArgs ) error {
149- log .Printf ("[ipam] Processing DEL command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}." ,
210+ log .Printf ("[cni- ipam] Processing DEL command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}." ,
150211 args .ContainerID , args .Netns , args .IfName , args .Args , args .Path )
151212
152213 // Parse network configuration from stdin.
153214 nwCfg , err := cni .ParseNetworkConfig (args .StdinData )
154215 if err != nil {
155- log .Printf ("[ipam] Failed to parse network configuration: %v." , err )
216+ log .Printf ("[cni- ipam] Failed to parse network configuration: %v." , err )
156217 return nil
157218 }
158219
159- log .Printf ("[ipam] Read network configuration %+v." , nwCfg )
220+ log .Printf ("[cni- ipam] Read network configuration %+v." , nwCfg )
160221
161222 // Assume default address space if not specified.
162223 if nwCfg .Ipam .AddrSpace == "" {
@@ -168,19 +229,19 @@ func (plugin *ipamPlugin) Delete(args *cniSkel.CmdArgs) error {
168229 // Release the address.
169230 err := plugin .am .ReleaseAddress (nwCfg .Ipam .AddrSpace , nwCfg .Ipam .Subnet , nwCfg .Ipam .Address )
170231 if err != nil {
171- log .Printf ("[cni] Failed to release address, err:%v." , err )
232+ log .Printf ("[cni-ipam ] Failed to release address, err:%v." , err )
172233 return nil
173234 }
174235 } else {
175236 // Release the pool.
176237 err := plugin .am .ReleasePool (nwCfg .Ipam .AddrSpace , nwCfg .Ipam .Subnet )
177238 if err != nil {
178- log .Printf ("[cni] Failed to release pool, err:%v." , err )
239+ log .Printf ("[cni-ipam ] Failed to release pool, err:%v." , err )
179240 return nil
180241 }
181242 }
182243
183- log .Printf ("[ipam] DEL succeeded." )
244+ log .Printf ("[cni- ipam] DEL succeeded." )
184245
185- return err
246+ return nil
186247}
0 commit comments