4
4
package networkcontainers
5
5
6
6
import (
7
+ "bytes"
8
+ "encoding/json"
7
9
"errors"
8
10
"fmt"
11
+ "go/types"
12
+ "io/ioutil"
9
13
"net"
14
+ "os"
15
+ "os/exec"
10
16
11
17
"github.com/Azure/azure-container-networking/cns"
12
18
"github.com/Azure/azure-container-networking/log"
19
+ "github.com/containernetworking/cni/libcni"
20
+ "github.com/containernetworking/cni/pkg/invoke"
21
+ )
22
+
23
+ const (
24
+ versionStr = "cniVersion"
25
+ pluginsStr = "plugins"
26
+ nameStr = "name"
27
+ k8sPodNamespaceStr = "K8S_POD_NAMESPACE"
28
+ k8sPodNameStr = "K8S_POD_NAME"
29
+ k8sPodInfraContainerStr = "K8S_POD_INFRA_CONTAINER_ID"
30
+ cniAdd = "ADD"
31
+ cniDelete = "DEL"
32
+ cniUpdate = "UPDATE"
13
33
)
14
34
15
35
// NetworkContainers can be used to perform operations on network containers.
16
36
type NetworkContainers struct {
17
37
logpath string
18
38
}
19
39
40
+ // NetPluginConfiguration represent network plugin configuration that is used during Update operation
41
+ type NetPluginConfiguration struct {
42
+ path string
43
+ networkConfigPath string
44
+ }
45
+
46
+ // NewNetPluginConfiguration create a new netplugin configuration.
47
+ func NewNetPluginConfiguration (binPath string , configPath string ) * NetPluginConfiguration {
48
+ return & NetPluginConfiguration {
49
+ path : binPath ,
50
+ networkConfigPath : configPath ,
51
+ }
52
+ }
53
+
20
54
func interfaceExists (iFaceName string ) (bool , error ) {
21
55
_ , err := net .InterfaceByName (iFaceName )
22
56
if err != nil {
@@ -40,9 +74,9 @@ func (cn *NetworkContainers) Create(createNetworkContainerRequest cns.CreateNetw
40
74
}
41
75
42
76
// Update updates a network container.
43
- func (cn * NetworkContainers ) Update (createNetworkContainerRequest cns.CreateNetworkContainerRequest ) error {
77
+ func (cn * NetworkContainers ) Update (createNetworkContainerRequest cns.CreateNetworkContainerRequest , netpluginConfig * NetPluginConfiguration ) error {
44
78
log .Printf ("[Azure CNS] NetworkContainers.Update called" )
45
- err := createOrUpdateInterface (createNetworkContainerRequest )
79
+ err := updateInterface (createNetworkContainerRequest , netpluginConfig )
46
80
if err == nil {
47
81
err = setWeakHostOnInterface (createNetworkContainerRequest .PrimaryInterfaceIdentifier )
48
82
}
@@ -57,3 +91,105 @@ func (cn *NetworkContainers) Delete(networkContainerID string) error {
57
91
log .Printf ("[Azure CNS] NetworkContainers.Delete finished." )
58
92
return err
59
93
}
94
+
95
+ // This function gets the flattened network configuration (compliant with azure cni) in byte array format
96
+ func getNetworkConfig (configFilePath string ) ([]byte , error ) {
97
+ content , err := ioutil .ReadFile (configFilePath )
98
+ if err != nil {
99
+ return nil , err
100
+ }
101
+
102
+ var configMap map [string ]interface {}
103
+ if err = json .Unmarshal (content , & configMap ); err != nil {
104
+ log .Printf ("[Azure CNS] Failed to unmarshal network configuration with error %v" , err )
105
+ return nil , err
106
+ }
107
+
108
+ // Get the plugins section
109
+ var flatNetConfigMap map [string ]interface {}
110
+ if pluginsSection , ok := configMap [pluginsStr ]; ok && len (pluginsSection .([]interface {})) > 0 {
111
+ flatNetConfigMap = pluginsSection .([]interface {})[0 ].(map [string ]interface {})
112
+ }
113
+
114
+ if flatNetConfigMap == nil {
115
+ msg := "[Azure CNS] " + pluginsStr + " section of the network configuration cannot be empty."
116
+ log .Printf (msg )
117
+ return nil , errors .New (msg )
118
+ }
119
+
120
+ // insert version and name fields
121
+ flatNetConfigMap [versionStr ] = configMap [versionStr ].(string )
122
+ flatNetConfigMap [nameStr ] = configMap [nameStr ].(string )
123
+
124
+ // convert into bytes format
125
+ netConfig , err := json .Marshal (flatNetConfigMap )
126
+ if err != nil {
127
+ log .Printf ("[Azure CNS] Failed to marshal flat network configuration with error %v" , err )
128
+ return nil , err
129
+ }
130
+
131
+ return netConfig , nil
132
+ }
133
+
134
+ func args (action , path string , rt * libcni.RuntimeConf ) * invoke.Args {
135
+ return & invoke.Args {
136
+ Command : action ,
137
+ ContainerID : rt .ContainerID ,
138
+ NetNS : rt .NetNS ,
139
+ PluginArgs : rt .Args ,
140
+ IfName : rt .IfName ,
141
+ Path : path ,
142
+ }
143
+ }
144
+
145
+ func pluginErr (err error , output []byte ) error {
146
+ if err != nil {
147
+ if _ , ok := err .(* exec.ExitError ); ok {
148
+ emsg := types.Error {}
149
+ if err := json .Unmarshal (output , & emsg ); err != nil {
150
+ emsg .Msg = fmt .Sprintf ("netplugin failed but error parsing its diagnostic message %s: %+v" , string (output ), err )
151
+ }
152
+
153
+ return & emsg
154
+ }
155
+ }
156
+
157
+ return err
158
+ }
159
+
160
+ func execPlugin (rt * libcni.RuntimeConf , netconf []byte , operation , path string ) error {
161
+ switch operation {
162
+ case cniAdd :
163
+ fallthrough
164
+ case cniDelete :
165
+ fallthrough
166
+ case cniUpdate :
167
+ environ := args (operation , path , rt ).AsEnv ()
168
+ log .Printf ("[Azure CNS] CNI called with environ variables %v" , environ )
169
+ stdout := & bytes.Buffer {}
170
+ command := exec .Command (path + string (os .PathSeparator ) + "azure-vnet" )
171
+ command .Env = environ
172
+ command .Stdin = bytes .NewBuffer (netconf )
173
+ command .Stdout = stdout
174
+ command .Stderr = os .Stderr
175
+ return pluginErr (command .Run (), stdout .Bytes ())
176
+ default :
177
+ return fmt .Errorf ("[Azure CNS] Invalid operation being passed to CNI: %s" , operation )
178
+ }
179
+ }
180
+
181
+ // Attach - attaches network container to network.
182
+ func (cn * NetworkContainers ) Attach (podName , podNamespace , dockerContainerid string , netPluginConfig * NetPluginConfiguration ) error {
183
+ log .Printf ("[Azure CNS] NetworkContainers.Attach called" )
184
+ err := configureNetworkContainerNetworking (cniAdd , podName , podNamespace , dockerContainerid , netPluginConfig )
185
+ log .Printf ("[Azure CNS] NetworkContainers.Attach finished" )
186
+ return err
187
+ }
188
+
189
+ // Detach - attaches network container to network.
190
+ func (cn * NetworkContainers ) Detach (podName , podNamespace , dockerContainerid string , netPluginConfig * NetPluginConfiguration ) error {
191
+ log .Printf ("[Azure CNS] NetworkContainers.Detach called" )
192
+ err := configureNetworkContainerNetworking (cniDelete , podName , podNamespace , dockerContainerid , netPluginConfig )
193
+ log .Printf ("[Azure CNS] NetworkContainers.Detach finished" )
194
+ return err
195
+ }
0 commit comments