@@ -35,8 +35,12 @@ type CNI interface {
3535 Setup (ctx context.Context , id string , path string , opts ... NamespaceOpts ) (* Result , error )
3636 // SetupSerially sets up each of the network interfaces for the namespace in serial
3737 SetupSerially (ctx context.Context , id string , path string , opts ... NamespaceOpts ) (* Result , error )
38+ //SetupNetworks sets up a list of networks
39+ SetupNetworks (ctx context.Context , id string , path string , networks []* Network , opts ... NamespaceOpts ) (* Result , error )
3840 // Remove tears down the network of the namespace.
3941 Remove (ctx context.Context , id string , path string , opts ... NamespaceOpts ) error
42+ // RemoveNetworks tears down a list of provided networks
43+ RemoveNetworks (ctx context.Context , id string , path string , networks []* Network , opts ... NamespaceOpts ) error
4044 // Check checks if the network is still in desired state
4145 Check (ctx context.Context , id string , path string , opts ... NamespaceOpts ) error
4246 // Load loads the cni network config
@@ -45,6 +49,8 @@ type CNI interface {
4549 Status () error
4650 // GetConfig returns a copy of the CNI plugin configurations as parsed by CNI
4751 GetConfig () * ConfigResult
52+ //BuildMultiNetwork returns a list of networks that match the network name in the cni cache
53+ BuildMultiNetwork (networkNames []* NetworkInterface ) []* Network
4854}
4955
5056type ConfigResult struct {
@@ -83,6 +89,11 @@ type libcni struct {
8389 sync.RWMutex
8490}
8591
92+ type NetworkInterface struct {
93+ NetworkName string
94+ InterfaceName string
95+ }
96+
8697func defaultCNIConfig () * libcni {
8798 return & libcni {
8899 config : config {
@@ -183,15 +194,62 @@ func (c *libcni) SetupSerially(ctx context.Context, id string, path string, opts
183194 return c .createResult (result )
184195}
185196
197+ // BuildMultiNetwork build dynamic list of Networks. Order Matters here!
198+ func (c * libcni ) BuildMultiNetwork (networkNames []* NetworkInterface ) []* Network {
199+ var network []* Network
200+ ifaceindex := 0
201+ for _ , net := range c .Networks () {
202+ for _ , x := range networkNames {
203+ if net .config .Name == x .NetworkName {
204+ if x .InterfaceName == "" {
205+ net .ifName = getIfName (c .prefix , ifaceindex )
206+ } else {
207+ net .ifName = x .InterfaceName
208+ }
209+ //Doing this to ensure first selected cni conf ifname is eth0
210+ if net .ifName != "lo" {
211+ ifaceindex ++
212+ }
213+
214+ //TODO - Add logic to make sure interface collisions don't happen. However that could be an implementation detail.
215+ network = append (network , net )
216+ }
217+ }
218+ }
219+
220+ return network
221+ }
222+
223+ // SetupSerially setups specific networks in the namespace and returns a Result
224+ func (c * libcni ) SetupNetworks (ctx context.Context , id string , path string , networks []* Network , opts ... NamespaceOpts ) (* Result , error ) {
225+ if err := c .Status (); err != nil {
226+ return nil , err
227+ }
228+ ns , err := newNamespace (id , path , opts ... )
229+ if err != nil {
230+ return nil , err
231+ }
232+ result , err := c .attachWithMultipleNetworksSerially (ctx , ns , networks )
233+ if err != nil {
234+ return nil , err
235+ }
236+ return c .createResult (result )
237+ }
238+
186239func (c * libcni ) attachNetworksSerially (ctx context.Context , ns * Namespace ) ([]* types100.Result , error ) {
240+ return c .attachWithMultipleNetworksSerially (ctx , ns , c .Networks ())
241+ }
242+
243+ func (c * libcni ) attachWithMultipleNetworksSerially (ctx context.Context , ns * Namespace , networks []* Network ) ([]* types100.Result , error ) {
187244 var results []* types100.Result
188- for _ , network := range c . Networks () {
245+ for _ , network := range networks {
189246 r , err := network .Attach (ctx , ns )
190247 if err != nil {
191248 return nil , err
192249 }
193250 results = append (results , r )
194251 }
252+
195253 return results , nil
196254}
197255
@@ -258,6 +316,33 @@ func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...Nam
258316 return nil
259317}
260318
319+ func (c * libcni ) RemoveNetworks (ctx context.Context , id string , path string , networks []* Network , opts ... NamespaceOpts ) error {
320+ if err := c .Status (); err != nil {
321+ return err
322+ }
323+ ns , err := newNamespace (id , path , opts ... )
324+ if err != nil {
325+ return err
326+ }
327+ for i := len (networks ) - 1 ; i >= 0 ; i -- {
328+ if err := networks [i ].Remove (ctx , ns ); err != nil {
329+ // Based on CNI spec v0.7.0, empty network namespace is allowed to
330+ // do best effort cleanup. However, it is not handled consistently
331+ // right now:
332+ // https://github.com/containernetworking/plugins/issues/210
333+ // TODO(random-liu): Remove the error handling when the issue is
334+ // fixed and the CNI spec v0.6.0 support is deprecated.
335+ // NOTE(claudiub): Some CNIs could return a "not found" error, which could mean that
336+ // it was already deleted.
337+ if (path == "" && strings .Contains (err .Error (), "no such file or directory" )) || strings .Contains (err .Error (), "not found" ) {
338+ continue
339+ }
340+ return err
341+ }
342+ }
343+ return nil
344+ }
345+
261346// Check checks if the network is still in desired state
262347func (c * libcni ) Check (ctx context.Context , id string , path string , opts ... NamespaceOpts ) error {
263348 if err := c .Status (); err != nil {
0 commit comments