github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/network/debinterfaces/bridge_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package debinterfaces_test
     5  
     6  import (
     7  	"runtime"
     8  
     9  	gc "gopkg.in/check.v1"
    10  
    11  	"github.com/juju/juju/network/debinterfaces"
    12  	"github.com/juju/testing"
    13  )
    14  
    15  type BridgeSuite struct {
    16  	testing.IsolationSuite
    17  
    18  	expander debinterfaces.WordExpander
    19  }
    20  
    21  var _ = gc.Suite(&BridgeSuite{})
    22  
    23  func (s *BridgeSuite) SetUpSuite(c *gc.C) {
    24  	if runtime.GOOS == "windows" {
    25  		c.Skip("skipping ActivationSuite tests on windows")
    26  	}
    27  	s.IsolationSuite.SetUpSuite(c)
    28  }
    29  
    30  func format(stanzas []debinterfaces.Stanza) string {
    31  	return debinterfaces.FormatStanzas(stanzas, 4)
    32  }
    33  
    34  func (s *BridgeSuite) SetUpTest(c *gc.C) {
    35  	s.expander = debinterfaces.NewWordExpander()
    36  }
    37  
    38  func (s *BridgeSuite) assertParse(c *gc.C, content string) []debinterfaces.Stanza {
    39  	stanzas, err := debinterfaces.ParseSource("", content, s.expander)
    40  	c.Assert(err, gc.IsNil)
    41  	return stanzas
    42  }
    43  
    44  func (s *BridgeSuite) checkBridge(input, expected string, c *gc.C, devices map[string]string) {
    45  	stanzas := s.assertParse(c, input)
    46  	bridged := debinterfaces.Bridge(stanzas, devices)
    47  	c.Check(format(bridged), gc.Equals, expected)
    48  	s.assertParse(c, format(bridged))
    49  }
    50  
    51  func (s *BridgeSuite) checkBridgeUnchanged(input string, c *gc.C, devices map[string]string) {
    52  	stanzas := s.assertParse(c, input)
    53  	bridged := debinterfaces.Bridge(stanzas, devices)
    54  	c.Check(format(bridged), gc.Equals, input[1:])
    55  	s.assertParse(c, format(bridged))
    56  }
    57  
    58  func (s *BridgeSuite) TestBridgeDeviceNameNotMatched(c *gc.C) {
    59  	input := `
    60  auto eth0
    61  iface eth0 inet manual`
    62  	s.checkBridgeUnchanged(input, c, map[string]string{"non-existent-interface": "br-non-existent"})
    63  }
    64  
    65  func (s *BridgeSuite) TestBridgeDeviceNameAlreadyBridged(c *gc.C) {
    66  	input := `
    67  auto br-eth0
    68  iface br-eth0 inet dhcp
    69      bridge_ports eth0`
    70  	s.checkBridgeUnchanged(input, c, map[string]string{"br-eth0": "br-eth0-2"})
    71  }
    72  
    73  func (s *BridgeSuite) TestBridgeDeviceIsBridgeable(c *gc.C) {
    74  	input := `
    75  auto eth0
    76  iface eth0 inet dhcp`
    77  
    78  	expected := `
    79  auto eth0
    80  iface eth0 inet manual
    81  
    82  auto br-eth0
    83  iface br-eth0 inet dhcp
    84      bridge_ports eth0`
    85  	s.checkBridge(input, expected[1:], c, map[string]string{"eth0": "br-eth0"})
    86  }
    87  
    88  func (s *BridgeSuite) TestBridgeDeviceIsBridgeableButHasNoAutoStanza(c *gc.C) {
    89  	input := `
    90  iface eth0 inet dhcp`
    91  
    92  	expected := `
    93  iface eth0 inet manual
    94  
    95  iface br-eth0 inet dhcp
    96      bridge_ports eth0`
    97  	s.checkBridge(input, expected[1:], c, map[string]string{"eth0": "br-eth0"})
    98  }
    99  
   100  func (s *BridgeSuite) TestBridgeDeviceIsNotBridgeable(c *gc.C) {
   101  	input := `
   102  iface work-wireless bootp`
   103  	s.checkBridgeUnchanged(input, c, map[string]string{"work-wireless": "br-work-wireless"})
   104  }
   105  
   106  func (s *BridgeSuite) TestBridgeSpecialOptionsGetMoved(c *gc.C) {
   107  	input := `
   108  auto eth0
   109  iface eth0 inet static
   110      mtu 1500
   111  
   112  auto eth1
   113  iface eth1 inet static
   114      address 192.168.1.254
   115      gateway 192.168.1.1
   116      netmask 255.255.255.0
   117      dns-nameservers 8.8.8.8
   118      dns-search ubuntu.com
   119      dns-sortlist 192.168.1.1/24 10.245.168.0/21 192.168.1.0/24
   120      mtu 1500`
   121  
   122  	expected := `
   123  auto eth0
   124  iface eth0 inet manual
   125      mtu 1500
   126  
   127  auto eth1
   128  iface eth1 inet manual
   129      mtu 1500
   130  
   131  auto br-eth0
   132  iface br-eth0 inet static
   133      bridge_ports eth0
   134  
   135  auto br-eth1
   136  iface br-eth1 inet static
   137      address 192.168.1.254
   138      gateway 192.168.1.1
   139      netmask 255.255.255.0
   140      dns-nameservers 8.8.8.8
   141      dns-search ubuntu.com
   142      dns-sortlist 192.168.1.1/24 10.245.168.0/21 192.168.1.0/24
   143      bridge_ports eth1`
   144  	s.checkBridge(input, expected[1:], c, map[string]string{"eth0": "br-eth0", "eth1": "br-eth1"})
   145  }
   146  
   147  func (s *BridgeSuite) TestBridgeVLAN(c *gc.C) {
   148  	input := `
   149  auto eth0.2
   150  iface eth0.2 inet static
   151      address 192.168.2.3/24
   152      vlan-raw-device eth0
   153      mtu 1500
   154      vlan_id 2`
   155  
   156  	expected := `
   157  auto eth0.2
   158  iface eth0.2 inet manual
   159      vlan-raw-device eth0
   160      mtu 1500
   161      vlan_id 2
   162  
   163  auto br-eth0.2
   164  iface br-eth0.2 inet static
   165      address 192.168.2.3/24
   166      bridge_ports eth0.2`
   167  	s.checkBridge(input, expected[1:], c, map[string]string{"eth0.2": "br-eth0.2"})
   168  }
   169  
   170  func (s *BridgeSuite) TestBridgeBond(c *gc.C) {
   171  	input := `
   172  auto eth0
   173  iface eth0 inet manual
   174      bond-miimon 100
   175      bond-master bond0
   176      bond-mode active-backup
   177      bond-lacp-rate slow
   178      bond-xmit-hash-policy layer2
   179      mtu 1500
   180  
   181  auto eth1
   182  iface eth1 inet manual
   183      bond-miimon 100
   184      bond-master bond0
   185      bond-mode active-backup
   186      bond-lacp-rate slow
   187      bond-xmit-hash-policy layer2
   188      mtu 1500
   189  
   190  auto bond0
   191  iface bond0 inet static
   192      address 10.17.20.211/24
   193      gateway 10.17.20.1
   194      dns-nameservers 10.17.20.200
   195      bond-slaves eth0 eth1
   196      bond-mode active-backup
   197      bond-xmit_hash_policy layer2
   198      bond-miimon 100
   199      mtu 1500
   200      hwaddress 52:54:00:1c:f1:5b
   201      bond-lacp_rate slow`
   202  
   203  	expected := `
   204  auto eth0
   205  iface eth0 inet manual
   206      bond-miimon 100
   207      bond-master bond0
   208      bond-mode active-backup
   209      bond-lacp-rate slow
   210      bond-xmit-hash-policy layer2
   211      mtu 1500
   212  
   213  auto eth1
   214  iface eth1 inet manual
   215      bond-miimon 100
   216      bond-master bond0
   217      bond-mode active-backup
   218      bond-lacp-rate slow
   219      bond-xmit-hash-policy layer2
   220      mtu 1500
   221  
   222  auto bond0
   223  iface bond0 inet manual
   224      bond-slaves eth0 eth1
   225      bond-mode active-backup
   226      bond-xmit_hash_policy layer2
   227      bond-miimon 100
   228      mtu 1500
   229      hwaddress 52:54:00:1c:f1:5b
   230      bond-lacp_rate slow
   231  
   232  auto br-bond0
   233  iface br-bond0 inet static
   234      address 10.17.20.211/24
   235      gateway 10.17.20.1
   236      dns-nameservers 10.17.20.200
   237      hwaddress 52:54:00:1c:f1:5b
   238      bridge_ports bond0`
   239  	s.checkBridge(input, expected[1:], c, map[string]string{"bond0": "br-bond0"})
   240  }
   241  
   242  func (s *BridgeSuite) TestBridgingIdempotent(c *gc.C) {
   243  	input := `
   244  auto eth0
   245  iface eth0 inet manual
   246      bond-miimon 100
   247      bond-master bond0
   248      bond-mode active-backup
   249      bond-lacp-rate slow
   250      bond-xmit-hash-policy layer2
   251      mtu 1500
   252  
   253  auto bond0
   254  iface bond0 inet manual
   255      bond-mode active-backup
   256      bond-xmit-hash-policy layer2
   257      hwaddress ether 7c:d3:0a:bb:e2:0a
   258      bond-slaves eth0
   259      mtu 1500
   260      bond-lacp-rate slow
   261      bond-miimon 100
   262  
   263  auto br-bond0
   264  iface br-bond0 inet static
   265      address 10.20.2.253/22
   266      gateway 10.20.0.1
   267      bridge_ports bond0`
   268  
   269  	s.checkBridgeUnchanged(input, c, map[string]string{"bond0": "br-bond0", "bond0.1000": "br-bond0.1000", "bond0.1001": "br-bond0.1001", "bond0.1002": "br-bond0.1002"})
   270  }
   271  
   272  func (s *BridgeSuite) TestBridgeNoIfacesDefined(c *gc.C) {
   273  	input := `
   274  mapping eth0
   275      script /path/to/pcmcia-compat.sh
   276      map home,*,*,*                  home
   277      map work,*,*,00:11:22:33:44:55  work-wireless
   278      map work,*,*,01:12:23:34:45:50  work-static`
   279  	s.checkBridgeUnchanged(input, c, map[string]string{"eth0": "br-eth0"})
   280  }
   281  
   282  func (s *BridgeSuite) TestBridgeBondMaster(c *gc.C) {
   283  	input := `
   284  auto ens5
   285  iface ens5 inet manual
   286      bond-lacp_rate slow
   287      mtu 1500
   288      bond-master bond0
   289      bond-xmit_hash_policy layer2
   290      bond-mode active-backup
   291      bond-miimon 100`
   292  	s.checkBridgeUnchanged(input, c, map[string]string{"ens5": "br-ens5"})
   293  }
   294  
   295  func (s *BridgeSuite) TestBridgeNoIfacesDefinedFromFile(c *gc.C) {
   296  	stanzas, err := debinterfaces.ParseSource("testdata/ifupdown-examples", nil, s.expander)
   297  	c.Assert(err, gc.IsNil)
   298  	input := format(stanzas)
   299  	s.checkBridge(input, input, c, map[string]string{"non-existent-interface": "non-existent-bridge"})
   300  }
   301  
   302  func (s *BridgeSuite) TestBridgeAlias(c *gc.C) {
   303  	input := `
   304  auto eth0
   305  iface eth0 inet static
   306      gateway 10.14.0.1
   307      address 10.14.0.102/24
   308  
   309  auto eth0:1
   310  iface eth0:1 inet static
   311      address 1.2.3.5`
   312  
   313  	expected := `
   314  auto eth0
   315  iface eth0 inet manual
   316  
   317  auto br-eth0:1
   318  iface br-eth0:1 inet static
   319      address 1.2.3.5
   320  
   321  auto br-eth0
   322  iface br-eth0 inet static
   323      gateway 10.14.0.1
   324      address 10.14.0.102/24
   325      bridge_ports eth0`
   326  	s.checkBridge(input, expected[1:], c, map[string]string{"eth0": "br-eth0", "eth0:1": "br-eth0:1"})
   327  }
   328  
   329  func (s *BridgeSuite) TestBridgeMultipleInterfaces(c *gc.C) {
   330  	input := `
   331  auto enp1s0f3
   332  iface enp1s0f3 inet static
   333    address 192.168.1.64/24
   334    gateway 192.168.1.254
   335    dns-nameservers 192.168.1.254
   336    dns-search home
   337  
   338  iface enp1s0f3 inet6 dhcp`
   339  
   340  	expected := `
   341  auto enp1s0f3
   342  iface enp1s0f3 inet manual
   343  
   344  iface enp1s0f3 inet6 manual
   345  
   346  auto br-enp1s0f3
   347  iface br-enp1s0f3 inet static
   348      address 192.168.1.64/24
   349      gateway 192.168.1.254
   350      dns-nameservers 192.168.1.254
   351      dns-search home
   352      bridge_ports enp1s0f3
   353  
   354  iface br-enp1s0f3 inet6 dhcp
   355      bridge_ports enp1s0f3`
   356  	s.checkBridge(input, expected[1:], c, map[string]string{"enp1s0f3": "br-enp1s0f3"})
   357  }
   358  
   359  func (s *BridgeSuite) TestSourceStanzaWithRelativeFilenames(c *gc.C) {
   360  	stanzas, err := debinterfaces.Parse("testdata/TestInputSourceStanza/interfaces")
   361  	c.Assert(err, gc.IsNil)
   362  	c.Assert(stanzas, gc.HasLen, 3)
   363  	bridged := debinterfaces.Bridge(stanzas, map[string]string{"eth0": "br-eth0"})
   364  
   365  	expected := `
   366  auto lo
   367  iface lo inet loopback
   368  
   369  auto eth0
   370  iface eth0 inet manual
   371  
   372  auto eth1
   373  iface eth1 inet static
   374      address 192.168.1.64
   375      dns-nameservers 192.168.1.254
   376  
   377  auto eth2
   378  iface eth2 inet manual
   379  
   380  auto br-eth0
   381  iface br-eth0 inet dhcp
   382      bridge_ports eth0`
   383  
   384  	c.Assert(debinterfaces.FormatStanzas(debinterfaces.FlattenStanzas(bridged), 4), gc.Equals, expected[1:])
   385  }
   386  
   387  func (s *BridgeSuite) TestSourceDirectoryStanzaWithRelativeFilenames(c *gc.C) {
   388  	stanzas, err := debinterfaces.Parse("testdata/TestInputSourceDirectoryStanza/interfaces")
   389  	c.Assert(err, gc.IsNil)
   390  	c.Assert(stanzas, gc.HasLen, 3)
   391  
   392  	bridged := debinterfaces.Bridge(stanzas, map[string]string{"eth3": "br-eth3"})
   393  
   394  	expected := `
   395  auto lo
   396  iface lo inet loopback
   397  
   398  auto eth3
   399  iface eth3 inet manual
   400  
   401  auto br-eth3
   402  iface br-eth3 inet static
   403      address 192.168.1.128
   404      dns-nameservers 192.168.1.254
   405      bridge_ports eth3`
   406  
   407  	c.Assert(debinterfaces.FormatStanzas(debinterfaces.FlattenStanzas(bridged), 4), gc.Equals, expected[1:])
   408  }
   409  
   410  func (s *BridgeSuite) TestBridgeInet6Only(c *gc.C) {
   411  	input := `
   412  auto enxe0db55e41d5b
   413  iface enxe0db55e41d5b inet6 static
   414      address 3ffe:1234:5678::1/64
   415      gateway 3ffe:1234:5678::2
   416  `
   417  	expected := `
   418  auto enxe0db55e41d5b
   419  iface enxe0db55e41d5b inet6 manual
   420  
   421  auto br-xe0db55e41d5b
   422  iface br-xe0db55e41d5b inet6 static
   423      address 3ffe:1234:5678::1/64
   424      gateway 3ffe:1234:5678::2
   425      bridge_ports enxe0db55e41d5b`
   426  
   427  	s.checkBridge(input, expected[1:], c, map[string]string{"enxe0db55e41d5b": "br-xe0db55e41d5b"})
   428  }