curtin fails to deploy on some invalid configs.

Bug #1734274 reported by Ondrej Kuchar
16
This bug affects 3 people
Affects Status Importance Assigned to Milestone
curtin
Triaged
Low
Unassigned

Bug Description

curtin version:
root@ba0b1a:~# dpkg -l | grep -i curtin
ii curtin-common 0.1.0~bzr532-0ubuntu1~16.04.1 all Library and tools for curtin installer
ii python3-curtin 0.1.0~bzr532-0ubuntu1~16.04.1 all Library and tools for curtin installer

curtin fails with this error

curtin: Installation started. (0.1.0~bzr532-0ubuntu1~16.04.1)
curtin: Installation failed with exception: 'NoneType' object has no attribute 'keys'

when the test in early_commands is not true
root@ba0b1a:~# cat /etc/maas/preseeds/curtin_userdata
#cloud-config
debconf_selections:
 maas: |
  {{for line in str(curtin_preseed).splitlines()}}
  {{line}}
  {{endfor}}
early_commands:
# disable_reboot: touch /run/block-curtin-poweroff /tmp/block-poweroff /tmp/block-reboot
{{if third_party_drivers and driver}}
  {{py: key_string = ''.join(['\\x%x' % x for x in map(ord, driver['key_binary'])])}}
  driver_00_get_key: /bin/echo -en '{{key_string}}' > /tmp/maas-{{driver['package']}}.gpg
  driver_01_add_key: ["apt-key", "add", "/tmp/maas-{{driver['package']}}.gpg"]
  driver_02_add: ["add-apt-repository", "-y", "deb {{driver['repository']}} {{node.get_distro_series()}} main"]
  driver_03_update_install: ["sh", "-c", "apt-get update --quiet && apt-get --assume-yes install {{driver['package']}}"]
  driver_04_load: ["sh", "-c", "depmod && modprobe {{driver['module']}}"]
{{endif}}

workaround was to add placeholder to early_commands
root@ba0b1a-mgm231maasregion-sk:~# cat /etc/maas/preseeds/curtin_userdata
#cloud-config
debconf_selections:
 maas: |
  {{for line in str(curtin_preseed).splitlines()}}
  {{line}}
  {{endfor}}
early_commands:
# disable_reboot: touch /run/block-curtin-poweroff /tmp/block-poweroff /tmp/block-reboot
  dummy_placeholder: echo just a placeholder
{{if third_party_drivers and driver}}
  {{py: key_string = ''.join(['\\x%x' % x for x in map(ord, driver['key_binary'])])}}
  driver_00_get_key: /bin/echo -en '{{key_string}}' > /tmp/maas-{{driver['package']}}.gpg
  driver_01_add_key: ["apt-key", "add", "/tmp/maas-{{driver['package']}}.gpg"]
  driver_02_add: ["add-apt-repository", "-y", "deb {{driver['repository']}} {{node.get_distro_series()}} main"]
  driver_03_update_install: ["sh", "-c", "apt-get update --quiet && apt-get --assume-yes install {{driver['package']}}"]
  driver_04_load: ["sh", "-c", "depmod && modprobe {{driver['module']}}"]
{{endif}}

Related bugs:
 * bug 1734391: user editing of preseed files is difficult due to maas internal data

Ante Karamatić (ivoks)
tags: added: cpe-onsite
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Hi,
I'm glad to hear that you have a workaround for now.
I checked most recent in the repo, but it works for me atm.
There are no changes from r532 (what you have) to r542 (head) that would affect this.

Given that you have a workaround IMHO we can wait for Scott to take a look at on monday.
I'll attach a test ...

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Can be run to see output like:
nosetests -v --nocapture tests/unittests/test_pack.py:TestPack.test_pseudo_install_empty

Might be a good test to be added (without the print's) in general.
But so far this proves to me that something else must be important in your case - as the empty command just works without your error.

$ nosetests -v --nocapture tests/unittests/test_pack.py:TestPack.test_pseudo_install_empty
test_pseudo_install_empty (unittests.test_pack.TestPack) ... {"sources": {"testsrc": "file:///tmp/curtin-TestPack.C9umk_/NOT_USED"}, "stages": ["early"], "early_commands": {}, "install": {"log_file": "/tmp/curtin-TestPack.C9umk_/tmpByespe"}}
DEBUG: cfg
{'stages': ['early'], 'early_commands': {}}
DEBUG: out
curtin: Installation started. (0.1.0~bzr542)
curtin: Installation finished.

ok

----------------------------------------------------------------------
Ran 1 test in 1.052s

OK

Revision history for this message
Ondrej Kuchar (ondrej-kuchar) wrote :

how does your config look like ?
don't you have the driver test like this ?

{{if third_party_drivers and driver}}
early_commands:

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

If you could check what the effective full generated config would be that might help to spot the root cause.

Revision history for this message
Ondrej Kuchar (ondrej-kuchar) wrote :

this is the full config: (I'm not sure what you mean by generated)

#cloud-config
debconf_selections:
 maas: |
  {{for line in str(curtin_preseed).splitlines()}}
  {{line}}
  {{endfor}}
early_commands:
# disable_reboot: touch /run/block-curtin-poweroff /tmp/block-poweroff /tmp/block-reboot
  dummy_placeholder: echo just a placeholder
{{if third_party_drivers and driver}}
  {{py: key_string = ''.join(['\\x%x' % x for x in map(ord, driver['key_binary'])])}}
  driver_00_get_key: /bin/echo -en '{{key_string}}' > /tmp/maas-{{driver['package']}}.gpg
  driver_01_add_key: ["apt-key", "add", "/tmp/maas-{{driver['package']}}.gpg"]
  driver_02_add: ["add-apt-repository", "-y", "deb {{driver['repository']}} {{node.get_distro_series()}} main"]
  driver_03_update_install: ["sh", "-c", "apt-get update --quiet && apt-get --assume-yes install {{driver['package']}}"]
  driver_04_load: ["sh", "-c", "depmod && modprobe {{driver['module']}}"]
{{endif}}
late_commands:
  maas: [wget, '--no-proxy', {{node_disable_pxe_url|escape.json}}, '--post-data', {{node_disable_pxe_data|escape.json}}, '-O', '/dev/null']
  add_ca_1: ["curtin", "in-target", "--", "wget", "--output-document", "/usr/local/share/ca-certificates/local.crt", "http://100.107.0.4/conf/ca.pem" ]
  add_ca_2: ["curtin", "in-target", "--", "wget", "--output-document", "/usr/local/share/ca-certificates/pannetss-ica1.crt", "http://100.107.0.4/conf/pannet/pannetss-ica1.crt" ]
  add_ca_3: ["curtin", "in-target", "--", "wget", "--output-document", "/usr/local/share/ca-certificates/pannetss-root.crt", "http://100.107.0.4/conf/pannet/pannetss-root.crt" ]
  add_ca_4: ["curtin", "in-target", "--", "update-ca-certificates"]
{{if third_party_drivers and driver}}
  driver_00_key_get: curtin in-target -- sh -c "/bin/echo -en '{{key_string}}' > /tmp/maas-{{driver['package']}}.gpg"
  driver_02_key_add: ["curtin", "in-target", "--", "apt-key", "add", "/tmp/maas-{{driver['package']}}.gpg"]
  driver_03_add: ["curtin", "in-target", "--", "add-apt-repository", "-y", "deb {{driver['repository']}} {{node.get_distro_series()}} main"]
  driver_04_update_install: ["curtin", "in-target", "--", "apt-get", "update", "--quiet"]
  driver_05_install: ["curtin", "in-target", "--", "apt-get", "-y", "install", "{{driver['package']}}"]
  driver_06_depmod: ["curtin", "in-target", "--", "depmod"]
  driver_07_update_initramfs: ["curtin", "in-target", "--", "update-initramfs", "-u"]
{{endif}}
showtrace: true
verbosity: 3

Revision history for this message
Gábor Mészáros (gabor.meszaros) wrote :

attaching a console output of the issue

Revision history for this message
Scott Moser (smoser) wrote :

I had put up a merge proposal a while ago at
 https://code.launchpad.net/~smoser/maas/+git/maas/+merge/332573
that covers this basic issue.
The preseeds files in /etc/ are quite non-trivial to edit.
My solution in that mp was to empty out the maas internal sections from there
as they're not really expected to be editable anyway.
If my merge proposal above was taken it would at least be more obvious to the user what they were writing in the config. Any complexity would have been their own additions.

From curtin's perspective it got garbage config. early_commands is supposed to be a dictionary. There are a few different things curtin could do to improve the situation:

a.) provide a schema or other mechanism for config validation that maas could use. That would allow maas to provide the user with an earlier error.
b.) explicitly allow <stage>_commands entries to be None.
c.) give a better error.

'b' sounds reasonable, but I suspect would have just resulted in the user not getting the result they were looking for. The install may have finished but just not done what they wanted.

Changed in curtin:
status: New → Triaged
importance: Undecided → Low
summary: - curtin fails to deploy on empty config values
+ curtin fails to deploy on some invalid configs.
Revision history for this message
Gábor Mészáros (gabor.meszaros) wrote :

curtin succeeds with indentation before first line comment:
early_commands:
  #disable_reboot: touch /run/block-curtin-poweroff /tmp/block-poweroff /tmp/block-reboot
{{if third_party_drivers and driver}}
  {{py: key_string = ''.join(['\\x%x' % x for x in map(ord, driver['key_binary'])])}}
...

vs. fails with no indentation:
early_commands:
# disable_reboot: touch /run/block-curtin-poweroff /tmp/block-poweroff /tmp/block-reboot
{{if third_party_drivers and driver}}
  {{py: key_string = ''.join(['\\x%x' % x for x in map(ord, driver['key_binary'])])}}
...

Revision history for this message
Scott Moser (smoser) wrote :

Gabor, the file ends up rendered (through MAAS's tempita) into yaml.
That yaml then needs to define a dictionary for 'early_commands'.

I can't provide an easy way to test MAAS's rendering of tempita.

But this shows the problem easily:

$ cat my.cfg
install:
 log_file: /tmp/out.log
stages: [early]
early_commands:
 # does not matter

$ curtin -vvv --showtrace install --config=my.cfg my.cfg | pastebinit
http://paste.ubuntu.com/26034970/

Revision history for this message
Scott Moser (smoser) wrote :

I opened bug 1734391, updated my merge proposal and linked the mp to the bug.

description: updated
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.