Skip to content

Commit 54be5fe

Browse files
ashvindeodharsharmasushant
authored andcommitted
azure-vnet: Implement GET command as per CNI 0.4.0 spec (#161)
* azure-vnet: Implement GET command
1 parent c22b4da commit 54be5fe

File tree

8 files changed

+184
-37
lines changed

8 files changed

+184
-37
lines changed

cni/cni.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const (
1111
// CNI commands.
1212
Cmd = "CNI_COMMAND"
1313
CmdAdd = "ADD"
14+
CmdGet = "GET"
1415
CmdDel = "DEL"
1516

1617
// CNI errors.
@@ -21,10 +22,11 @@ const (
2122
)
2223

2324
// Supported CNI versions.
24-
var supportedVersions = []string{"0.1.0", "0.2.0", "0.3.0", "0.3.1"}
25+
var supportedVersions = []string{"0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0"}
2526

2627
// CNI contract.
2728
type PluginApi interface {
2829
Add(args *cniSkel.CmdArgs) error
30+
Get(args *cniSkel.CmdArgs) error
2931
Delete(args *cniSkel.CmdArgs) error
3032
}

cni/ipam/ipam.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,11 @@ func (plugin *ipamPlugin) Add(args *cniSkel.CmdArgs) error {
250250
return nil
251251
}
252252

253+
// Get handles CNI Get commands.
254+
func (plugin *ipamPlugin) Get(args *cniSkel.CmdArgs) error {
255+
return nil
256+
}
257+
253258
// Delete handles CNI delete commands.
254259
func (plugin *ipamPlugin) Delete(args *cniSkel.CmdArgs) error {
255260
var err error

cni/network/network.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@ import (
1616
"github.com/Azure/azure-container-networking/telemetry"
1717

1818
cniSkel "github.com/containernetworking/cni/pkg/skel"
19+
cniTypes "github.com/containernetworking/cni/pkg/types"
1920
cniTypesCurr "github.com/containernetworking/cni/pkg/types/current"
2021
)
2122

2223
const (
2324
// Plugin name.
2425
name = "azure-vnet"
26+
27+
// Supported IP version. Currently support only IPv4
28+
ipVersion = "4"
2529
)
2630

2731
// NetPlugin represents the CNI network plugin.
@@ -362,6 +366,90 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
362366
return nil
363367
}
364368

369+
// Get handles CNI Get commands.
370+
func (plugin *netPlugin) Get(args *cniSkel.CmdArgs) error {
371+
var (
372+
result cniTypesCurr.Result
373+
err error
374+
nwCfg *cni.NetworkConfig
375+
epInfo *network.EndpointInfo
376+
iface *cniTypesCurr.Interface
377+
)
378+
379+
log.Printf("[cni-net] Processing GET command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}.",
380+
args.ContainerID, args.Netns, args.IfName, args.Args, args.Path)
381+
382+
defer func() {
383+
// Add Interfaces to result.
384+
iface = &cniTypesCurr.Interface{
385+
Name: args.IfName,
386+
}
387+
result.Interfaces = append(result.Interfaces, iface)
388+
389+
if err == nil {
390+
// Convert result to the requested CNI version.
391+
res, err := result.GetAsVersion(nwCfg.CNIVersion)
392+
if err != nil {
393+
err = plugin.Error(err)
394+
}
395+
// Output the result to stdout.
396+
res.Print()
397+
}
398+
399+
log.Printf("[cni-net] GET command completed with result:%+v err:%v.", result, err)
400+
}()
401+
402+
// Parse network configuration from stdin.
403+
nwCfg, err = cni.ParseNetworkConfig(args.StdinData)
404+
if err != nil {
405+
err = plugin.Errorf("Failed to parse network configuration: %v.", err)
406+
return err
407+
}
408+
409+
log.Printf("[cni-net] Read network configuration %+v.", nwCfg)
410+
411+
// Initialize values from network config.
412+
networkId := nwCfg.Name
413+
endpointId := GetEndpointID(args)
414+
415+
// Query the network.
416+
_, err = plugin.nm.GetNetworkInfo(networkId)
417+
if err != nil {
418+
plugin.Errorf("Failed to query network: %v", err)
419+
return err
420+
}
421+
422+
// Query the endpoint.
423+
epInfo, err = plugin.nm.GetEndpointInfo(networkId, endpointId)
424+
if err != nil {
425+
plugin.Errorf("Failed to query endpoint: %v", err)
426+
return err
427+
}
428+
429+
for _, ipAddresses := range epInfo.IPAddresses {
430+
ipConfig := &cniTypesCurr.IPConfig{
431+
Version: ipVersion,
432+
Interface: &epInfo.IfIndex,
433+
Address: ipAddresses,
434+
}
435+
436+
if epInfo.Gateways != nil {
437+
ipConfig.Gateway = epInfo.Gateways[0]
438+
}
439+
440+
result.IPs = append(result.IPs, ipConfig)
441+
}
442+
443+
for _, route := range epInfo.Routes {
444+
result.Routes = append(result.Routes, &cniTypes.Route{Dst: route.Dst, GW: route.Gw})
445+
}
446+
447+
result.DNS.Nameservers = epInfo.DNS.Servers
448+
result.DNS.Domain = epInfo.DNS.Suffix
449+
450+
return nil
451+
}
452+
365453
// Delete handles CNI delete commands.
366454
func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error {
367455
var err error

cni/network/plugin/main.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,29 +83,42 @@ func main() {
8383

8484
netPlugin.SetReportManager(reportManager)
8585

86-
err = netPlugin.Start(&config)
87-
if err != nil {
86+
defer func() {
87+
if errUninit := netPlugin.Plugin.UninitializeKeyValueStore(); errUninit != nil {
88+
log.Printf("Failed to uninitialize key-value store of network plugin, err:%v.\n", err)
89+
}
90+
91+
if recover() != nil {
92+
os.Exit(1)
93+
}
94+
}()
95+
96+
if err = netPlugin.Plugin.InitializeKeyValueStore(&config); err != nil {
97+
log.Printf("Failed to initialize key-value store of network plugin, err:%v.\n", err)
98+
reportPluginError(reportManager, err)
99+
panic("network plugin fatal error")
100+
}
101+
102+
if err = netPlugin.Start(&config); err != nil {
88103
log.Printf("Failed to start network plugin, err:%v.\n", err)
89104
reportPluginError(reportManager, err)
90-
os.Exit(1)
105+
panic("network plugin fatal error")
91106
}
92107

93-
err = netPlugin.Execute(cni.PluginApi(netPlugin))
94-
if err != nil {
108+
if err = netPlugin.Execute(cni.PluginApi(netPlugin)); err != nil {
95109
log.Printf("Failed to execute network plugin, err:%v.\n", err)
96110
reportPluginError(reportManager, err)
97111
}
98112

99113
netPlugin.Stop()
100114

101115
if err != nil {
102-
os.Exit(1)
116+
panic("network plugin fatal error")
103117
}
104118

105119
// Report CNI successfully finished execution.
106120
reportManager.Report.CniSucceeded = true
107-
err = reportManager.SendReport()
108-
if err != nil {
121+
if err = reportManager.SendReport(); err != nil {
109122
log.Printf("SendReport failed due to %v", err)
110123
} else {
111124
markSendReport(reportManager)

cni/plugin.go

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,37 +51,11 @@ func (plugin *Plugin) Initialize(config *common.PluginConfig) error {
5151
log.Printf("[cni] Failed to configure logging, err:%v.\n", err)
5252
return err
5353
}
54-
55-
// Initialize store.
56-
if plugin.Store == nil {
57-
// Create the key value store.
58-
var err error
59-
plugin.Store, err = store.NewJsonFileStore(platform.CNIRuntimePath + plugin.Name + ".json")
60-
if err != nil {
61-
log.Printf("[cni] Failed to create store, err:%v.", err)
62-
return err
63-
}
64-
65-
// Acquire store lock.
66-
err = plugin.Store.Lock(true)
67-
if err != nil {
68-
log.Printf("[cni] Timed out on locking store, err:%v.", err)
69-
return err
70-
}
71-
72-
config.Store = plugin.Store
73-
}
74-
7554
return nil
7655
}
7756

7857
// Uninitialize uninitializes the plugin.
7958
func (plugin *Plugin) Uninitialize() {
80-
err := plugin.Store.Unlock()
81-
if err != nil {
82-
log.Printf("[cni] Failed to unlock store, err:%v.", err)
83-
}
84-
8559
plugin.Plugin.Uninitialize()
8660
}
8761

@@ -109,7 +83,7 @@ func (plugin *Plugin) Execute(api PluginApi) (err error) {
10983
pluginInfo := cniVers.PluginSupports(supportedVersions...)
11084

11185
// Parse args and call the appropriate cmd handler.
112-
cniErr := cniSkel.PluginMainWithError(api.Add, api.Delete, pluginInfo)
86+
cniErr := cniSkel.PluginMainWithError(api.Add, api.Get, api.Delete, pluginInfo)
11387
if cniErr != nil {
11488
cniErr.Print()
11589
return cniErr
@@ -177,3 +151,40 @@ func (plugin *Plugin) Error(err error) *cniTypes.Error {
177151
func (plugin *Plugin) Errorf(format string, args ...interface{}) *cniTypes.Error {
178152
return plugin.Error(fmt.Errorf(format, args...))
179153
}
154+
155+
// Initialize key-value store
156+
func (plugin *Plugin) InitializeKeyValueStore(config *common.PluginConfig) error {
157+
// Create the key value store.
158+
if plugin.Store == nil {
159+
var err error
160+
plugin.Store, err = store.NewJsonFileStore(platform.CNIRuntimePath + plugin.Name + ".json")
161+
if err != nil {
162+
log.Printf("[cni] Failed to create store, err:%v.", err)
163+
return err
164+
}
165+
}
166+
167+
// Acquire store lock.
168+
if err := plugin.Store.Lock(true); err != nil {
169+
log.Printf("[cni] Timed out on locking store, err:%v.", err)
170+
return err
171+
}
172+
173+
config.Store = plugin.Store
174+
175+
return nil
176+
}
177+
178+
// Uninitialize key-value store
179+
func (plugin *Plugin) UninitializeKeyValueStore() error {
180+
if plugin.Store != nil {
181+
err := plugin.Store.Unlock()
182+
if err != nil {
183+
log.Printf("[cni] Failed to unlock store, err:%v.", err)
184+
return err
185+
}
186+
}
187+
plugin.Store = nil
188+
189+
return nil
190+
}

network/endpoint.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type endpoint struct {
2121
MacAddress net.HardwareAddr
2222
IPAddresses []net.IPNet
2323
Gateways []net.IP
24+
DNS DNSInfo
25+
Routes []RouteInfo
2426
}
2527

2628
// EndpointInfo contains read-only information about an endpoint.
@@ -29,10 +31,14 @@ type EndpointInfo struct {
2931
ContainerID string
3032
NetNsPath string
3133
IfName string
34+
SandboxKey string
35+
IfIndex int
36+
MacAddress net.HardwareAddr
37+
DNS DNSInfo
3238
IPAddresses []net.IPNet
3339
Routes []RouteInfo
34-
DNS DNSInfo
3540
Policies []policy.Policy
41+
Gateways []net.IP
3642
Data map[string]interface{}
3743
}
3844

@@ -144,6 +150,18 @@ func (ep *endpoint) getInfo() *EndpointInfo {
144150
Id: ep.Id,
145151
IPAddresses: ep.IPAddresses,
146152
Data: make(map[string]interface{}),
153+
MacAddress: ep.MacAddress,
154+
SandboxKey: ep.SandboxKey,
155+
IfIndex: 0, // Azure CNI supports only one interface
156+
DNS: ep.DNS,
157+
}
158+
159+
for _, route := range ep.Routes {
160+
info.Routes = append(info.Routes, route)
161+
}
162+
163+
for _, gw := range ep.Gateways {
164+
info.Gateways = append(info.Gateways, gw)
147165
}
148166

149167
// Call the platform implementation.

network/endpoint_linux.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
222222
MacAddress: containerIf.HardwareAddr,
223223
IPAddresses: epInfo.IPAddresses,
224224
Gateways: []net.IP{nw.extIf.IPv4Gateway},
225+
DNS: epInfo.DNS,
226+
}
227+
228+
for _, route := range epInfo.Routes {
229+
ep.Routes = append(ep.Routes, route)
225230
}
226231

227232
return ep, nil

network/endpoint_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
7070
IfName: epInfo.IfName,
7171
IPAddresses: epInfo.IPAddresses,
7272
Gateways: []net.IP{net.ParseIP(hnsResponse.GatewayAddress)},
73+
DNS: epInfo.DNS,
74+
}
75+
76+
for _, route := range epInfo.Routes {
77+
ep.Routes = append(ep.Routes, route)
7378
}
7479

7580
ep.MacAddress, _ = net.ParseMAC(hnsResponse.MacAddress)

0 commit comments

Comments
 (0)