** Description changed:

-  mask2cidr error with integer value - argument of type 'int' is not
+ http://pad.lv/1684349
+ https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1684349
+     
+ [Impact]
+ On Openstack instances, when rendering sysconfig output, cloud-init 
+ would stacktrace due to a TypeError.
+ This affects runtime only when rendering sysconfig networking, which
+ is what is used on CentOS and RedHat systems.
+ 
+ [Test Case]
+ The basic idea below is:
+  a.) launch an instance with proposed version of cloud-init.
+  b.) inside instance, get cloud-init's network rendering tool from trunk
+  c.) run the rendering tool against a config that failed before.
+  d.) check rendered netplan config to verify it has the correct format.
+      The failed output would have 'addresses' with a format like:
+      172.19.1.34/255.255.255.0
+      The expected output would be 'cidr' format:
+      172.19.1.34/24
+ 
+ ## launch an instance.
+ $ release=xenial
+ $ ref=$release-proposed
+ $ lxc-proposed-snapshot --proposed --publish $release $ref
+ $ lxc launch $ref $name
+ $ lxc exec $name
+ 
+ ## get render tool
+ % wget 
https://git.launchpad.net/~cloud-init-dev/cloud-init/plain/tools/net-convert.py 
-O net-convert.py
+ 
+ ## write the network_data.json
+ % cat > simple-ipv6.yaml <<EOF
+ version: 1
+ config:
+   - type: physical
+     name: eth0
+     subnets:
+      - type: static
+        address: "2000:192:168::5"
+        netmask: 64
+        routes:
+         - netmask: 0
+           gateway: "2000:192:168::1"
+           network: "::"
+ EOF
+ 
+ ## run the converter
+ % ./net-convert.py --network-data=simple-ipv6.yaml \
+      --kind=yaml --output-kind=eni --directory=out.d
+ 
+ ## check the output
+ % cat out.d/etc/network/interfaces
+ auto lo
+ iface lo inet loopback
+ 
+ auto eth0
+ iface eth0 inet6 static
+     address 2000:192:168::5
+     netmask 64
+     post-up route add -A inet6 default gw 2000:192:168::1 || true
+     pre-down route del -A inet6 default gw 2000:192:168::1 || true
+ 
+ 
+ ## show the cloud-init versions
+ % dpkg-query --show cloud-init
+ ...
+ 
+ [Regression Potential] 
+ The fix here was just to make a common networking method accept
+ a string input as intended rather than only an integer.
+ 
+ The common code changes could shake out other failures in the networking
+ path.
+ 
+ [Other Info]
+ Upstream commit at
+   https://git.launchpad.net/cloud-init/commit/?id=16a7302f6a
+ 
+ lxc-proposed-snapshot is
+   
https://git.launchpad.net/~smoser/cloud-init/+git/sru-info/tree/bin/lxc-proposed-snapshot
+ It publishes an image to lxd with proposed enabled and cloud-init upgraded.
+ === End SRU Template ===
+ 
+ mask2cidr error with integer value - argument of type 'int' is not
  iterable
  
  ~~~
  def mask2cidr(mask):
-     if ':' in str(mask):
-         return ipv6mask2cidr(mask)
-     elif '.' in mask:
-         return ipv4mask2cidr(mask)
-     else:
-         return mask
+     if ':' in str(mask):
+         return ipv6mask2cidr(mask)
+     elif '.' in mask:
+         return ipv4mask2cidr(mask)
+     else:
+         return mask
  ~~~
  
  is not type safe. It tries to take into account that this can be a
  prefix (so it does not contain ':' not '.' and then return mask. The
  problem is that if mask is an integer, then this returns:
  
  ~~~
  Traceback (most recent call last):
-   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 513, in 
status_wrapper
-     ret = functor(name, args)
-   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 269, in 
main_init
-     init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
-   File "/usr/lib/python2.7/site-packages/cloudinit/stages.py", line 641, in 
apply_network_config
-     return self.distro.apply_network_config(netcfg, bring_up=bring_up)
-   File "/usr/lib/python2.7/site-packages/cloudinit/distros/__init__.py", line 
150, in apply_network_config
-     dev_names = self._write_network_config(netconfig)
-   File "/usr/lib/python2.7/site-packages/cloudinit/distros/rhel.py", line 59, 
in _write_network_config
-     ns = parse_net_config_data(netconfig)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 32, in parse_net_config_data
-     nsi.parse_config(skip_broken=skip_broken)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 205, in parse_config
-     handler(self, command)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 78, in decorator
-     return func(self, command, *args, **kwargs)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 239, in handle_physical
-     subnet['netmask'] = mask2cidr(subnet['netmask'])
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 441, in mask2cidr
-     elif '.' in mask:
+   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 513, in 
status_wrapper
+     ret = functor(name, args)
+   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 269, in 
main_init
+     init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
+   File "/usr/lib/python2.7/site-packages/cloudinit/stages.py", line 641, in 
apply_network_config
+     return self.distro.apply_network_config(netcfg, bring_up=bring_up)
+   File "/usr/lib/python2.7/site-packages/cloudinit/distros/__init__.py", line 
150, in apply_network_config
+     dev_names = self._write_network_config(netconfig)
+   File "/usr/lib/python2.7/site-packages/cloudinit/distros/rhel.py", line 59, 
in _write_network_config
+     ns = parse_net_config_data(netconfig)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 32, in parse_net_config_data
+     nsi.parse_config(skip_broken=skip_broken)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 205, in parse_config
+     handler(self, command)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 78, in decorator
+     return func(self, command, *args, **kwargs)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 239, in handle_physical
+     subnet['netmask'] = mask2cidr(subnet['netmask'])
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 441, in mask2cidr
+     elif '.' in mask:
  ~~~
  
  Made a modification to the code to troubleshoot this:
  ~~~
-        # convert subnet ipv6 netmask to cidr as needed
-         subnets = command.get('subnets')
-         print subnets
-         if subnets:
-             for subnet in subnets:
-                 if subnet['type'] == 'static':
-                     if 'netmask' in subnet and ':' in subnet['address']:
-                         subnet['netmask'] = mask2cidr(subnet['netmask'])
-                         for route in subnet.get('routes', []):
-                             if 'netmask' in route:
-                                 route['netmask'] = mask2cidr(route['netmask'])
+        # convert subnet ipv6 netmask to cidr as needed
+         subnets = command.get('subnets')
+         print subnets
+         if subnets:
+             for subnet in subnets:
+                 if subnet['type'] == 'static':
+                     if 'netmask' in subnet and ':' in subnet['address']:
+                         subnet['netmask'] = mask2cidr(subnet['netmask'])
+                         for route in subnet.get('routes', []):
+                             if 'netmask' in route:
+                                 route['netmask'] = mask2cidr(route['netmask'])
  ~~~
  
  This error can be hit on RHEL when running the following 2x (don't know
  why 2x):
  
-  rm -Rf /var/lib/cloud/data/*  ; cloud-init --force init
+  rm -Rf /var/lib/cloud/data/*  ; cloud-init --force init
  
  On the second run, this will be returned:
  ~~~
  Traceback (most recent call last):
-   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 513, in 
status_wrapper
-     ret = functor(name, args)
-   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 269, in 
main_init
-     init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
-   File "/usr/lib/python2.7/site-packages/cloudinit/stages.py", line 641, in 
apply_network_config
-     return self.distro.apply_network_config(netcfg, bring_up=bring_up)
-   File "/usr/lib/python2.7/site-packages/cloudinit/distros/__init__.py", line 
150, in apply_network_config
-     dev_names = self._write_network_config(netconfig)
-   File "/usr/lib/python2.7/site-packages/cloudinit/distros/rhel.py", line 59, 
in _write_network_config
-     ns = parse_net_config_data(netconfig)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 32, in parse_net_config_data
-     nsi.parse_config(skip_broken=skip_broken)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 205, in parse_config
-     handler(self, command)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 78, in decorator
-     return func(self, command, *args, **kwargs)
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 239, in handle_physical
-     subnet['netmask'] = mask2cidr(subnet['netmask'])
-   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 441, in mask2cidr
-     elif '.' in mask:
+   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 513, in 
status_wrapper
+     ret = functor(name, args)
+   File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 269, in 
main_init
+     init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
+   File "/usr/lib/python2.7/site-packages/cloudinit/stages.py", line 641, in 
apply_network_config
+     return self.distro.apply_network_config(netcfg, bring_up=bring_up)
+   File "/usr/lib/python2.7/site-packages/cloudinit/distros/__init__.py", line 
150, in apply_network_config
+     dev_names = self._write_network_config(netconfig)
+   File "/usr/lib/python2.7/site-packages/cloudinit/distros/rhel.py", line 59, 
in _write_network_config
+     ns = parse_net_config_data(netconfig)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 32, in parse_net_config_data
+     nsi.parse_config(skip_broken=skip_broken)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 205, in parse_config
+     handler(self, command)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 78, in decorator
+     return func(self, command, *args, **kwargs)
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 239, in handle_physical
+     subnet['netmask'] = mask2cidr(subnet['netmask'])
+   File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 441, in mask2cidr
+     elif '.' in mask:
  TypeError: argument of type 'int' is not iterable
  ------------------------------------------------------------
  [{u'routes': [{u'netmask': u'0.0.0.0', u'network': u'0.0.0.0', u'gateway': 
u'192.168.0.1'}], u'netmask': u'255.255.255.0', u'type': 'static', 'ipv4': 
True, 'address': u'192.168.0.11'}, {u'routes': [{u'netmask': 0, u'network': 
u'::', u'gateway': u'2000:192:168::1'}], u'netmask': 64, 'ipv6': True, u'type': 
'static', 'address': u'2000:192:168::4'}]
  ~~~
  
  not the `u'netmask': 64` integer
  
  This can be fixed by changing the code to:
  ~~~
  def mask2cidr(mask):
-     if ':' in str(mask):
-         return ipv6mask2cidr(mask)
-     elif '.' in str(mask):
-         return ipv4mask2cidr(mask)
-     else:
-         return mask
+     if ':' in str(mask):
+         return ipv6mask2cidr(mask)
+     elif '.' in str(mask):
+         return ipv4mask2cidr(mask)
+     else:
+         return mask
  ~~~

** Description changed:

- http://pad.lv/1684349
- https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1684349
-     
+ === Begin SRU Template ===
  [Impact]
- On Openstack instances, when rendering sysconfig output, cloud-init 
+ On Openstack instances, when rendering sysconfig output, cloud-init
  would stacktrace due to a TypeError.
  This affects runtime only when rendering sysconfig networking, which
  is what is used on CentOS and RedHat systems.
  
  [Test Case]
  The basic idea below is:
-  a.) launch an instance with proposed version of cloud-init.
-  b.) inside instance, get cloud-init's network rendering tool from trunk
-  c.) run the rendering tool against a config that failed before.
-  d.) check rendered netplan config to verify it has the correct format.
-      The failed output would have 'addresses' with a format like:
-      172.19.1.34/255.255.255.0
-      The expected output would be 'cidr' format:
-      172.19.1.34/24
+  a.) launch an instance with proposed version of cloud-init.
+  b.) inside instance, get cloud-init's network rendering tool from trunk
+  c.) run the rendering tool against a config that failed before.
+  d.) check rendered netplan config to verify it has the correct format.
+      The failed output would have 'addresses' with a format like:
+      172.19.1.34/255.255.255.0
+      The expected output would be 'cidr' format:
+      172.19.1.34/24
  
  ## launch an instance.
  $ release=xenial
  $ ref=$release-proposed
  $ lxc-proposed-snapshot --proposed --publish $release $ref
  $ lxc launch $ref $name
  $ lxc exec $name
  
  ## get render tool
  % wget 
https://git.launchpad.net/~cloud-init-dev/cloud-init/plain/tools/net-convert.py 
-O net-convert.py
  
  ## write the network_data.json
  % cat > simple-ipv6.yaml <<EOF
  version: 1
  config:
-   - type: physical
-     name: eth0
-     subnets:
-      - type: static
-        address: "2000:192:168::5"
-        netmask: 64
-        routes:
-         - netmask: 0
-           gateway: "2000:192:168::1"
-           network: "::"
+   - type: physical
+     name: eth0
+     subnets:
+      - type: static
+        address: "2000:192:168::5"
+        netmask: 64
+        routes:
+         - netmask: 0
+           gateway: "2000:192:168::1"
+           network: "::"
  EOF
  
  ## run the converter
  % ./net-convert.py --network-data=simple-ipv6.yaml \
-      --kind=yaml --output-kind=eni --directory=out.d
+      --kind=yaml --output-kind=eni --directory=out.d
  
  ## check the output
  % cat out.d/etc/network/interfaces
  auto lo
  iface lo inet loopback
  
  auto eth0
  iface eth0 inet6 static
-     address 2000:192:168::5
-     netmask 64
-     post-up route add -A inet6 default gw 2000:192:168::1 || true
-     pre-down route del -A inet6 default gw 2000:192:168::1 || true
- 
+     address 2000:192:168::5
+     netmask 64
+     post-up route add -A inet6 default gw 2000:192:168::1 || true
+     pre-down route del -A inet6 default gw 2000:192:168::1 || true
  
  ## show the cloud-init versions
  % dpkg-query --show cloud-init
  ...
  
- [Regression Potential] 
+ [Regression Potential]
  The fix here was just to make a common networking method accept
  a string input as intended rather than only an integer.
  
  The common code changes could shake out other failures in the networking
  path.
  
  [Other Info]
  Upstream commit at
-   https://git.launchpad.net/cloud-init/commit/?id=16a7302f6a
+   https://git.launchpad.net/cloud-init/commit/?id=16a7302f6a
  
  lxc-proposed-snapshot is
-   
https://git.launchpad.net/~smoser/cloud-init/+git/sru-info/tree/bin/lxc-proposed-snapshot
+   
https://git.launchpad.net/~smoser/cloud-init/+git/sru-info/tree/bin/lxc-proposed-snapshot
  It publishes an image to lxd with proposed enabled and cloud-init upgraded.
  === End SRU Template ===
  
  mask2cidr error with integer value - argument of type 'int' is not
  iterable
  
  ~~~
  def mask2cidr(mask):
      if ':' in str(mask):
          return ipv6mask2cidr(mask)
      elif '.' in mask:
          return ipv4mask2cidr(mask)
      else:
          return mask
  ~~~
  
  is not type safe. It tries to take into account that this can be a
  prefix (so it does not contain ':' not '.' and then return mask. The
  problem is that if mask is an integer, then this returns:
  
  ~~~
  Traceback (most recent call last):
    File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 513, in 
status_wrapper
      ret = functor(name, args)
    File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 269, in 
main_init
      init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
    File "/usr/lib/python2.7/site-packages/cloudinit/stages.py", line 641, in 
apply_network_config
      return self.distro.apply_network_config(netcfg, bring_up=bring_up)
    File "/usr/lib/python2.7/site-packages/cloudinit/distros/__init__.py", line 
150, in apply_network_config
      dev_names = self._write_network_config(netconfig)
    File "/usr/lib/python2.7/site-packages/cloudinit/distros/rhel.py", line 59, 
in _write_network_config
      ns = parse_net_config_data(netconfig)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 32, in parse_net_config_data
      nsi.parse_config(skip_broken=skip_broken)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 205, in parse_config
      handler(self, command)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 78, in decorator
      return func(self, command, *args, **kwargs)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 239, in handle_physical
      subnet['netmask'] = mask2cidr(subnet['netmask'])
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 441, in mask2cidr
      elif '.' in mask:
  ~~~
  
  Made a modification to the code to troubleshoot this:
  ~~~
         # convert subnet ipv6 netmask to cidr as needed
          subnets = command.get('subnets')
          print subnets
          if subnets:
              for subnet in subnets:
                  if subnet['type'] == 'static':
                      if 'netmask' in subnet and ':' in subnet['address']:
                          subnet['netmask'] = mask2cidr(subnet['netmask'])
                          for route in subnet.get('routes', []):
                              if 'netmask' in route:
                                  route['netmask'] = mask2cidr(route['netmask'])
  ~~~
  
  This error can be hit on RHEL when running the following 2x (don't know
  why 2x):
  
   rm -Rf /var/lib/cloud/data/*  ; cloud-init --force init
  
  On the second run, this will be returned:
  ~~~
  Traceback (most recent call last):
    File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 513, in 
status_wrapper
      ret = functor(name, args)
    File "/usr/lib/python2.7/site-packages/cloudinit/cmd/main.py", line 269, in 
main_init
      init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
    File "/usr/lib/python2.7/site-packages/cloudinit/stages.py", line 641, in 
apply_network_config
      return self.distro.apply_network_config(netcfg, bring_up=bring_up)
    File "/usr/lib/python2.7/site-packages/cloudinit/distros/__init__.py", line 
150, in apply_network_config
      dev_names = self._write_network_config(netconfig)
    File "/usr/lib/python2.7/site-packages/cloudinit/distros/rhel.py", line 59, 
in _write_network_config
      ns = parse_net_config_data(netconfig)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 32, in parse_net_config_data
      nsi.parse_config(skip_broken=skip_broken)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 205, in parse_config
      handler(self, command)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 78, in decorator
      return func(self, command, *args, **kwargs)
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 239, in handle_physical
      subnet['netmask'] = mask2cidr(subnet['netmask'])
    File "/usr/lib/python2.7/site-packages/cloudinit/net/network_state.py", 
line 441, in mask2cidr
      elif '.' in mask:
  TypeError: argument of type 'int' is not iterable
  ------------------------------------------------------------
  [{u'routes': [{u'netmask': u'0.0.0.0', u'network': u'0.0.0.0', u'gateway': 
u'192.168.0.1'}], u'netmask': u'255.255.255.0', u'type': 'static', 'ipv4': 
True, 'address': u'192.168.0.11'}, {u'routes': [{u'netmask': 0, u'network': 
u'::', u'gateway': u'2000:192:168::1'}], u'netmask': 64, 'ipv6': True, u'type': 
'static', 'address': u'2000:192:168::4'}]
  ~~~
  
  not the `u'netmask': 64` integer
  
  This can be fixed by changing the code to:
  ~~~
  def mask2cidr(mask):
      if ':' in str(mask):
          return ipv6mask2cidr(mask)
      elif '.' in str(mask):
          return ipv4mask2cidr(mask)
      else:
          return mask
  ~~~

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1684349

Title:
   mask2cidr error with integer value - argument of type 'int' is not
  iterable

To manage notifications about this bug go to:
https://bugs.launchpad.net/cloud-init/+bug/1684349/+subscriptions

-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to