Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openstack: read the dynamic metadata group vendor_data2.json #777

Merged
merged 22 commits into from
Feb 5, 2021

Conversation

andrewbogott
Copy link
Contributor

@andrewbogott andrewbogott commented Jan 19, 2021

Add support for openstack's dynamic vendor data, which appears under openstack/latest/vendor_data2.json

This adds vendor_data2 to all pathways; it should be a no-op for non-OpenStack providers.

Bug: https://bugs.launchpad.net/cloud-init/+bug/1841104

Andrew Bogott and others added 13 commits January 19, 2021 11:32
This has been present in the openestack metadata since version
'Newton'.

Bug: 1841104
Ubuntu cloud images ship /etc/cloud/build.info which includes a line
with the build serial used to identify the image:

    serial: 20210108

This is valuable information when verifying Ubuntu issues (to confirm
that testing is happening against the expected image), but is also
useful when debugging test failures: manifests of all packages in (the
base) images can be found at http://cloud-images.ubuntu.com/
The company name has two distinct words.

Signed-off-by: Dan Kenigsberg <danken@redhat.com>
Two shell code blocks are not marked as such, confusing rst to consider
them as yaml. Be explicit about their syntax, and use $ prompt to match
elsewhere in the docs.

/home/travis/build/canonical/cloud-init/doc/rtd/topics/format.rst:28: WARNING: Could not lex literal_block as "yaml". Highlighting skipped.
/home/travis/build/canonical/cloud-init/doc/rtd/topics/format.rst:52: WARNING: Could not lex literal_block as "yaml". Highlighting skipped.

Signed-off-by: Dan Kenigsberg <danken@redhat.com>
Copy link
Member

@TheRealFalcon TheRealFalcon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. Dynamic vendor data will be very useful.

Overall, this change looks good. I have a few comments inline. Additionally,

  1. Can you update the documentation to add a comment about dynamic vendordata / vendordata2 to the Vendor Data section of openstack.rst
  2. Can you run this against an openstack system with dynamic vendordata and provide some logs (cloud-init collect-logs)? Has it been tested against a live system with dynamic vendor data overriding static vendor data, and then also the user data overriding the vendor data? Based on the code, I have no real reason to question these things, but it's always good to have verification against a real system.

cloudinit/stages.py Outdated Show resolved Hide resolved
cloudinit/stages.py Outdated Show resolved Hide resolved
@TheRealFalcon TheRealFalcon self-assigned this Feb 2, 2021
@andrewbogott
Copy link
Contributor Author

andrewbogott commented Feb 3, 2021

I think I found a regression in the jinja handler (unrelated to my code but that interferes with getting a clean test). Please don't merge until I know what's up with that :)

ETA: logged as https://bugs.launchpad.net/cloud-init/+bug/1914641

@andrewbogott
Copy link
Contributor Author

Here's the output from a test run of this:

root@cloudinit-test:~# curl http://169.254.169.254/openstack/latest/vendor_data2.json
{"cloud-init": "MIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"XXXXboundary text\"\n\nThis is a multipart config in MIME format.\nIt contains a cloud-init config followed by\na first boot script.\n\n--XXXXboundary text\nMIME-Version: 1.0\nContent-Type: text/cloud-config; charset=\"us-ascii\"\n\nfqdn: cloudinit-test.andrewtestproject.codfw1dev.wikimedia.cloud-overridden-by-vendordata2\n\n--XXXXboundary text\nMIME-Version: 1.0\nContent-Type: text/text/x-shellscript; charset=\"us-ascii\"\n#!/bin/bash\n\nset -x\n\necho This is a boot script provided by dynamic vendordata\n\necho \"This came from vendordata2\" > /etc/proof_of_life.txt\n\n--XXXXboundary text"}

root@cloudinit-test:~# cat /etc/proof_of_life.txt
cat: /etc/proof_of_life.txt: No such file or directory

root@cloudinit-test:~# cloud-init clean && rm -f /var/log/cloud-init.log && rm -Rf /var/lib/cloud/* && cloud-init -d init && cloud-init -d modules --mode final
2021-02-04 17:52:31,733 - handlers.py[DEBUG]: start: init-network: searching for network datasources
2021-02-04 17:52:31,733 - util.py[DEBUG]: Reading from /proc/uptime (quiet=False)
2021-02-04 17:52:31,733 - util.py[DEBUG]: Read 18 bytes from /proc/uptime
2021-02-04 17:52:31,734 - util.py[DEBUG]: Reading from /var/lib/cloud/data/status.json (quiet=False)
2021-02-04 17:52:31,746 - atomic_helper.py[DEBUG]: Atomically writing to file /var/lib/cloud/data/status.json (via temporary file /var/lib/cloud/data/tmpn0xyv0wh) - w: [644] 463 bytes/chars
2021-02-04 17:52:31,747 - util.py[DEBUG]: Creating symbolic link from '/run/cloud-init/status.json' => '../../var/lib/cloud/data/status.json'
2021-02-04 17:52:31,747 - util.py[DEBUG]: Attempting to remove /run/cloud-init/status.json
2021-02-04 17:52:31,748 - subp.py[DEBUG]: Running command ['systemd-detect-virt', '--quiet', '--container'] with allowed return codes [0] (shell=False, capture=True)
2021-02-04 17:52:31,757 - util.py[DEBUG]: Reading from /etc/os-release (quiet=False)
2021-02-04 17:52:31,757 - util.py[DEBUG]: Read 261 bytes from /etc/os-release
2021-02-04 17:52:31,758 - util.py[DEBUG]: Reading from /proc/1/environ (quiet=False)
2021-02-04 17:52:31,758 - util.py[DEBUG]: Read 155 bytes from /proc/1/environ
2021-02-04 17:52:31,759 - util.py[DEBUG]: Reading from /proc/self/status (quiet=False)
2021-02-04 17:52:31,759 - util.py[DEBUG]: Read 1030 bytes from /proc/self/status
2021-02-04 17:52:31,759 - util.py[DEBUG]: Reading from /proc/cmdline (quiet=False)
2021-02-04 17:52:31,759 - util.py[DEBUG]: Read 151 bytes from /proc/cmdline
2021-02-04 17:52:31,759 - util.py[DEBUG]: Reading from /proc/uptime (quiet=False)
2021-02-04 17:52:31,760 - util.py[DEBUG]: Read 18 bytes from /proc/uptime
2021-02-04 17:52:31,760 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg (quiet=False)
2021-02-04 17:52:31,760 - util.py[DEBUG]: Read 3581 bytes from /etc/cloud/cloud.cfg
2021-02-04 17:52:31,760 - util.py[DEBUG]: Attempting to load yaml from string of length 3581 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:31,772 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/05_logging.cfg (quiet=False)
2021-02-04 17:52:31,772 - util.py[DEBUG]: Read 2070 bytes from /etc/cloud/cloud.cfg.d/05_logging.cfg
2021-02-04 17:52:31,772 - util.py[DEBUG]: Attempting to load yaml from string of length 2070 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:31,775 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg (quiet=False)
2021-02-04 17:52:31,776 - util.py[DEBUG]: Read 200 bytes from /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg
2021-02-04 17:52:31,776 - util.py[DEBUG]: Attempting to load yaml from string of length 200 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:31,776 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/00_debian.cfg (quiet=False)
2021-02-04 17:52:31,777 - util.py[DEBUG]: Read 93 bytes from /etc/cloud/cloud.cfg.d/00_debian.cfg
2021-02-04 17:52:31,777 - util.py[DEBUG]: Attempting to load yaml from string of length 93 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:31,779 - util.py[DEBUG]: Reading from /run/cloud-init/cloud.cfg (quiet=False)
2021-02-04 17:52:31,779 - util.py[DEBUG]: Read 37 bytes from /run/cloud-init/cloud.cfg
2021-02-04 17:52:31,779 - util.py[DEBUG]: Attempting to load yaml from string of length 37 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:31,780 - util.py[DEBUG]: Attempting to load yaml from string of length 0 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:31,780 - util.py[DEBUG]: loaded blob returned None, returning default.
2021-02-04 17:52:31,781 - util.py[DEBUG]: Redirecting <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> to | tee -a /var/log/cloud-init-output.log
2021-02-04 17:52:31,782 - util.py[DEBUG]: Redirecting <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'> to | tee -a /var/log/cloud-init-output.log
2021-02-04 17:52:31,783 - main.py[DEBUG]: Logging being reset, this logger may no longer be active shortly
Cloud-init v. 20.4 running 'init' at Thu, 04 Feb 2021 17:52:31 +0000. Up 70381.77 seconds.
ci-info: ++++++++++++++++++++++++++++++++++++++Net device info+++++++++++++++++++++++++++++++++++++++
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
ci-info: | Device |  Up  |           Address           |      Mask     | Scope  |     Hw-Address    |
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
ci-info: |  eth0  | True |        172.16.128.212       | 255.255.255.0 | global | fa:16:3e:f9:08:75 |
ci-info: |  eth0  | True | fe80::f816:3eff:fef9:875/64 |       .       |  link  | fa:16:3e:f9:08:75 |
ci-info: |   lo   | True |          127.0.0.1          |   255.0.0.0   |  host  |         .         |
ci-info: |   lo   | True |           ::1/128           |       .       |  host  |         .         |
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
ci-info: ++++++++++++++++++++++++++++++++Route IPv4 info+++++++++++++++++++++++++++++++++
ci-info: +-------+-----------------+--------------+-----------------+-----------+-------+
ci-info: | Route |   Destination   |   Gateway    |     Genmask     | Interface | Flags |
ci-info: +-------+-----------------+--------------+-----------------+-----------+-------+
ci-info: |   0   |     0.0.0.0     | 172.16.128.1 |     0.0.0.0     |    eth0   |   UG  |
ci-info: |   1   | 169.254.169.254 | 172.16.128.1 | 255.255.255.255 |    eth0   |  UGH  |
ci-info: |   2   |   172.16.128.0  |   0.0.0.0    |  255.255.255.0  |    eth0   |   U   |
ci-info: +-------+-----------------+--------------+-----------------+-----------+-------+
ci-info: +++++++++++++++++++Route IPv6 info+++++++++++++++++++
ci-info: +-------+-------------+---------+-----------+-------+
ci-info: | Route | Destination | Gateway | Interface | Flags |
ci-info: +-------+-------------+---------+-----------+-------+
ci-info: |   1   |  fe80::/64  |    ::   |    eth0   |   U   |
ci-info: |   3   |    local    |    ::   |    eth0   |   U   |
ci-info: |   4   |   ff00::/8  |    ::   |    eth0   |   U   |
ci-info: +-------+-------------+---------+-----------+-------+
Generating public/private rsa key pair.
Your identification has been saved in /etc/ssh/ssh_host_rsa_key.
Your public key has been saved in /etc/ssh/ssh_host_rsa_key.pub.
The key fingerprint is:
SHA256:Sll2h2HO8H2/Z/tZPtTk4h4WyLzI+SToR7Fa0x6dN4Y root@cloudinit-test
The key's randomart image is:
+---[RSA 2048]----+
|        . o      |
|         * +     |
|        o * o .  |
|       + ..+ o ..|
|      o S  ++.o+o|
|     . . o=ooE+==|
|      . .+=ooo=+=|
|       .. .+...==|
|        ..  ...o=|
+----[SHA256]-----+
Generating public/private dsa key pair.
Your identification has been saved in /etc/ssh/ssh_host_dsa_key.
Your public key has been saved in /etc/ssh/ssh_host_dsa_key.pub.
The key fingerprint is:
SHA256:Bo4zWLhpTI53WvfBFX8X3mWgAZYJe/+RuQOyyUshsmk root@cloudinit-test
The key's randomart image is:
+---[DSA 1024]----+
|        ..++. .oo|
|   .     ooo o..+|
|  o . . . o o ..o|
| = = o o o . . + |
|. O * + S o o +  |
| o + + * + = o o |
|  .   E . =   +  |
|     .   . .   . |
|          .      |
+----[SHA256]-----+
Generating public/private ecdsa key pair.
Your identification has been saved in /etc/ssh/ssh_host_ecdsa_key.
Your public key has been saved in /etc/ssh/ssh_host_ecdsa_key.pub.
The key fingerprint is:
SHA256:bn8G0WpN6XcAY41bV3pxa9CvEn7i0BBBPdJMMkJrPSY root@cloudinit-test
The key's randomart image is:
+---[ECDSA 256]---+
|       .o.=*.+..+|
|         +ooX +o=|
|        E += B.+o|
|       . oo.* o..|
|        S  X . o |
|       .  = B + .|
|        o. + = . |
|       . .  +    |
|          .o     |
+----[SHA256]-----+
Generating public/private ed25519 key pair.
Your identification has been saved in /etc/ssh/ssh_host_ed25519_key.
Your public key has been saved in /etc/ssh/ssh_host_ed25519_key.pub.
The key fingerprint is:
SHA256:G7/lrg3Vqo3kPtEbjWVUkIvxK4mzWijD0p8BcFTJ4Qw root@cloudinit-test
The key's randomart image is:
+--[ED25519 256]--+
|      Eooo    .+.|
|     . +o   . o  |
|    . . o    = . |
|     o      ..=  |
|      . S  o.*.. |
|     o . =+.*.o  |
|    . = + =+o+   |
|     . + *oX.    |
|        +oB+=    |
+----[SHA256]-----+
2021-02-04 17:52:38,911 - handlers.py[DEBUG]: start: modules-final: running modules for final
2021-02-04 17:52:38,911 - util.py[DEBUG]: Reading from /proc/uptime (quiet=False)
2021-02-04 17:52:38,912 - util.py[DEBUG]: Read 18 bytes from /proc/uptime
2021-02-04 17:52:38,912 - util.py[DEBUG]: Reading from /var/lib/cloud/data/status.json (quiet=False)
2021-02-04 17:52:38,912 - util.py[DEBUG]: Read 504 bytes from /var/lib/cloud/data/status.json
2021-02-04 17:52:38,925 - atomic_helper.py[DEBUG]: Atomically writing to file /var/lib/cloud/data/status.json (via temporary file /var/lib/cloud/data/tmpre4opgt8) - w: [644] 529 bytes/chars
2021-02-04 17:52:38,925 - util.py[DEBUG]: Creating symbolic link from '/run/cloud-init/status.json' => '../../var/lib/cloud/data/status.json'
2021-02-04 17:52:38,925 - util.py[DEBUG]: Attempting to remove /run/cloud-init/status.json
2021-02-04 17:52:38,926 - util.py[DEBUG]: Reading from /proc/uptime (quiet=False)
2021-02-04 17:52:38,926 - util.py[DEBUG]: Read 18 bytes from /proc/uptime
2021-02-04 17:52:38,926 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg (quiet=False)
2021-02-04 17:52:38,926 - util.py[DEBUG]: Read 3581 bytes from /etc/cloud/cloud.cfg
2021-02-04 17:52:38,927 - util.py[DEBUG]: Attempting to load yaml from string of length 3581 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,937 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/05_logging.cfg (quiet=False)
2021-02-04 17:52:38,937 - util.py[DEBUG]: Read 2070 bytes from /etc/cloud/cloud.cfg.d/05_logging.cfg
2021-02-04 17:52:38,937 - util.py[DEBUG]: Attempting to load yaml from string of length 2070 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,940 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg (quiet=False)
2021-02-04 17:52:38,941 - util.py[DEBUG]: Read 200 bytes from /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg
2021-02-04 17:52:38,941 - util.py[DEBUG]: Attempting to load yaml from string of length 200 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,941 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/00_debian.cfg (quiet=False)
2021-02-04 17:52:38,942 - util.py[DEBUG]: Read 93 bytes from /etc/cloud/cloud.cfg.d/00_debian.cfg
2021-02-04 17:52:38,942 - util.py[DEBUG]: Attempting to load yaml from string of length 93 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,944 - util.py[DEBUG]: Reading from /run/cloud-init/cloud.cfg (quiet=False)
2021-02-04 17:52:38,944 - util.py[DEBUG]: Read 37 bytes from /run/cloud-init/cloud.cfg
2021-02-04 17:52:38,944 - util.py[DEBUG]: Attempting to load yaml from string of length 37 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,945 - subp.py[DEBUG]: Running command ['systemd-detect-virt', '--quiet', '--container'] with allowed return codes [0] (shell=False, capture=True)
2021-02-04 17:52:38,954 - util.py[DEBUG]: Reading from /etc/os-release (quiet=False)
2021-02-04 17:52:38,954 - util.py[DEBUG]: Read 261 bytes from /etc/os-release
2021-02-04 17:52:38,955 - util.py[DEBUG]: Reading from /proc/1/environ (quiet=False)
2021-02-04 17:52:38,955 - util.py[DEBUG]: Read 155 bytes from /proc/1/environ
2021-02-04 17:52:38,955 - util.py[DEBUG]: Reading from /proc/self/status (quiet=False)
2021-02-04 17:52:38,955 - util.py[DEBUG]: Read 1030 bytes from /proc/self/status
2021-02-04 17:52:38,956 - util.py[DEBUG]: Reading from /proc/cmdline (quiet=False)
2021-02-04 17:52:38,956 - util.py[DEBUG]: Read 151 bytes from /proc/cmdline
2021-02-04 17:52:38,956 - util.py[DEBUG]: Attempting to load yaml from string of length 0 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,956 - util.py[DEBUG]: loaded blob returned None, returning default.
2021-02-04 17:52:38,957 - util.py[DEBUG]: Reading from /var/lib/cloud/instance/cloud-config.txt (quiet=False)
2021-02-04 17:52:38,957 - util.py[DEBUG]: Read 0 bytes from /var/lib/cloud/instance/cloud-config.txt
2021-02-04 17:52:38,957 - util.py[DEBUG]: Attempting to load yaml from string of length 0 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,957 - util.py[DEBUG]: loaded blob returned None, returning default.
2021-02-04 17:52:38,958 - util.py[DEBUG]: Reading from /var/lib/cloud/instance/vendor2-cloud-config.txt (quiet=False)
2021-02-04 17:52:38,958 - util.py[DEBUG]: Read 141 bytes from /var/lib/cloud/instance/vendor2-cloud-config.txt
2021-02-04 17:52:38,958 - util.py[DEBUG]: Attempting to load yaml from string of length 141 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,959 - handlers.py[DEBUG]: start: modules-final/check-cache: attempting to read from cache [trust]
2021-02-04 17:52:38,959 - util.py[DEBUG]: Reading from /var/lib/cloud/instance/obj.pkl (quiet=False)
2021-02-04 17:52:38,960 - util.py[DEBUG]: Read 12115 bytes from /var/lib/cloud/instance/obj.pkl
2021-02-04 17:52:38,964 - util.py[DEBUG]: Reading from /run/cloud-init/.instance-id (quiet=False)
2021-02-04 17:52:38,964 - util.py[DEBUG]: Read 37 bytes from /run/cloud-init/.instance-id
2021-02-04 17:52:38,964 - stages.py[DEBUG]: restored from cache with run check: DataSourceOpenStack [net,ver=2]
2021-02-04 17:52:38,964 - handlers.py[DEBUG]: finish: modules-final/check-cache: SUCCESS: restored from cache with run check: DataSourceOpenStack [net,ver=2]
2021-02-04 17:52:38,965 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg (quiet=False)
2021-02-04 17:52:38,965 - util.py[DEBUG]: Read 3581 bytes from /etc/cloud/cloud.cfg
2021-02-04 17:52:38,965 - util.py[DEBUG]: Attempting to load yaml from string of length 3581 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,976 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/05_logging.cfg (quiet=False)
2021-02-04 17:52:38,976 - util.py[DEBUG]: Read 2070 bytes from /etc/cloud/cloud.cfg.d/05_logging.cfg
2021-02-04 17:52:38,976 - util.py[DEBUG]: Attempting to load yaml from string of length 2070 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,979 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg (quiet=False)
2021-02-04 17:52:38,979 - util.py[DEBUG]: Read 200 bytes from /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg
2021-02-04 17:52:38,979 - util.py[DEBUG]: Attempting to load yaml from string of length 200 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,980 - util.py[DEBUG]: Reading from /etc/cloud/cloud.cfg.d/00_debian.cfg (quiet=False)
2021-02-04 17:52:38,980 - util.py[DEBUG]: Read 93 bytes from /etc/cloud/cloud.cfg.d/00_debian.cfg
2021-02-04 17:52:38,980 - util.py[DEBUG]: Attempting to load yaml from string of length 93 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,981 - util.py[DEBUG]: Reading from /run/cloud-init/cloud.cfg (quiet=False)
2021-02-04 17:52:38,981 - util.py[DEBUG]: Read 37 bytes from /run/cloud-init/cloud.cfg
2021-02-04 17:52:38,982 - util.py[DEBUG]: Attempting to load yaml from string of length 37 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,982 - util.py[DEBUG]: Attempting to load yaml from string of length 0 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,982 - util.py[DEBUG]: loaded blob returned None, returning default.
2021-02-04 17:52:38,983 - util.py[DEBUG]: Reading from /var/lib/cloud/instance/cloud-config.txt (quiet=False)
2021-02-04 17:52:38,983 - util.py[DEBUG]: Read 0 bytes from /var/lib/cloud/instance/cloud-config.txt
2021-02-04 17:52:38,983 - util.py[DEBUG]: Attempting to load yaml from string of length 0 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,983 - util.py[DEBUG]: loaded blob returned None, returning default.
2021-02-04 17:52:38,983 - util.py[DEBUG]: Reading from /var/lib/cloud/instance/vendor2-cloud-config.txt (quiet=False)
2021-02-04 17:52:38,984 - util.py[DEBUG]: Read 141 bytes from /var/lib/cloud/instance/vendor2-cloud-config.txt
2021-02-04 17:52:38,984 - util.py[DEBUG]: Attempting to load yaml from string of length 141 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,985 - main.py[DEBUG]: Closing stdin
2021-02-04 17:52:38,985 - util.py[DEBUG]: Reading from /var/lib/cloud/instance/cloud-config.txt (quiet=False)
2021-02-04 17:52:38,985 - util.py[DEBUG]: Read 0 bytes from /var/lib/cloud/instance/cloud-config.txt
2021-02-04 17:52:38,985 - util.py[DEBUG]: Attempting to load yaml from string of length 0 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,986 - util.py[DEBUG]: loaded blob returned None, returning default.
2021-02-04 17:52:38,986 - util.py[DEBUG]: Reading from /var/lib/cloud/instance/vendor2-cloud-config.txt (quiet=False)
2021-02-04 17:52:38,986 - util.py[DEBUG]: Read 141 bytes from /var/lib/cloud/instance/vendor2-cloud-config.txt
2021-02-04 17:52:38,986 - util.py[DEBUG]: Attempting to load yaml from string of length 141 with allowed root types (<class 'dict'>,)
2021-02-04 17:52:38,987 - util.py[DEBUG]: Redirecting <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> to | tee -a /var/log/cloud-init-output.log
2021-02-04 17:52:38,989 - util.py[DEBUG]: Redirecting <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'> to | tee -a /var/log/cloud-init-output.log
2021-02-04 17:52:38,989 - main.py[DEBUG]: Logging being reset, this logger may no longer be active shortly
Cloud-init v. 20.4 running 'modules:final' at Thu, 04 Feb 2021 17:52:38 +0000. Up 70388.94 seconds.
+ echo This is a boot script provided by dynamic vendordata
This is a boot script provided by dynamic vendordata
+ echo 'This came from vendordata2'
ci-info: no authorized SSH keys fingerprints found for user ubuntu.
Cloud-init v. 20.4 finished at Thu, 04 Feb 2021 17:52:39 +0000. Datasource DataSourceOpenStack [net,ver=2].  Up 70389.12 seconds

root@cloudinit-test:~# cat /etc/proof_of_life.txt
This came from vendordata2

root@cloudinit-test:~# hostname -f
cloudinit-test.andrewtestproject.codfw1dev.wikimedia.cloud-overridden-by-vendordata2

@andrewbogott
Copy link
Contributor Author

I've logged the jinja regression as 1914641; I believe it's not a blocker for this patch.

Copy link
Member

@TheRealFalcon TheRealFalcon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the refactor! Just a couple minor changes left.

cloudinit/stages.py Outdated Show resolved Hide resolved
doc/rtd/topics/datasources/openstack.rst Outdated Show resolved Hide resolved
Andrew Bogott and others added 3 commits February 4, 2021 19:21
@TheRealFalcon TheRealFalcon merged commit 3cebe0d into canonical:master Feb 5, 2021
@andrewbogott
Copy link
Contributor Author

Thank you @TheRealFalcon

@smoser smoser mentioned this pull request Mar 10, 2021
3 tasks
@@ -392,6 +395,11 @@ def get_vendordata(self):
self.vendordata = self.ud_proc.process(self.get_vendordata_raw())
return self.vendordata

def get_vendordata2(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not have been put here. A single datasource (openstack) has a thing called 'vendordata2'. Shouldn't the change have been made in openstack datasource rather than propagating up to the base class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @smoser. I'm looking at how to move this handling into openstack-specific code and it's starting to seem like a pretty big refactor. It's easy enough to move the things from init.py into DataSourceOpenStack.py but then the vendordata2 handlers in stages.py will need to be made aware of which subclasses do or don't support vendordata2; failing that we could subclass things in stages.py but as best I can tell that isn't currently done anywhere so would require some additional scaffolding.

If you still want me to go ahead with refactoring I can work on it but I welcome your thoughts about how to avoid littering the existing code with checks :) It might also be worth creating a new bug to track.

(Of course when I wrote the initial patchset I was imagining that this might be a feature that other datasources would want to implement but that may not be realistic.)

-Andrew

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Of course when I wrote the initial patchset I was imagining that this might be a feature that other datasources would want to implement but that may not be realistic.)

I'm confused as to how that would be any different than vendor data to cloud-init.

As far as rework, i would have thought that you would just change the datasource to say : If there is vendor-data2, present it as vendor-data, otherwise use vendor-data.

@mmahalwa
Copy link

Hi @smoser @TheRealFalcon @andrewbogott
I am working with OpenStack Pike and cloud-init 21.1. I am able to successfully pass dynamic vendor data to the config drive of an instance. However, cloud-init 21.1 just reads all the 'x' bytes of the vendor_data2.json but it doesn't execute the contents of the json. Although, static vendor data works perfectly fine and the YAML file in the JSON is executed as expected by cloud-init 21.1

Relevant part from the cloud-init.log looks like this:


2021-04-09 10:51:47,104 - util.py[DEBUG]: Reading from /cfgdrive/openstack/2017-02-22/vendor_data2.json (quiet=False)
2021-04-09 10:51:47,114 - util.py[DEBUG]: Read 74 bytes from /cfgdrive/openstack/2017-02-22/vendor_data2.json
2021-04-09 10:52:02,332 - util.py[DEBUG]: Writing to /var/lib/cloud/instances/74eeba86-84b8-4599-856e-88413029ebc8/vendor-data.txt - wb: [600] 0 bytes
2021-04-09 10:52:02,335 - util.py[DEBUG]: Writing to /var/lib/cloud/instances/74eeba86-84b8-4599-856e-88413029ebc8/vendor-data.txt.i - wb: [600] 308 bytes
2021-04-09 10:52:02,336 - util.py[DEBUG]: Writing to /var/lib/cloud/instances/74eeba86-84b8-4599-856e-88413029ebc8/vendor-data2.txt - wb: [600] 0 bytes
2021-04-09 10:52:02,338 - util.py[DEBUG]: Writing to /var/lib/cloud/instances/74eeba86-84b8-4599-856e-88413029ebc8/vendor-data2.txt.i - wb: [600] 308 bytes
.
.
.
2021-04-09 10:52:02,352 - handlers.py[DEBUG]: start: init-network/consume-vendor-data2: reading and applying vendor-data2
2021-04-09 10:52:02,352 - stages.py[DEBUG]: no vendordata2 from datasource

It reads the 74 bytes but doesn't write the value (the YAML file) mapped to key "cloud-init" to the file to vendor-data2.txt, because it was not able to find "vendordata2 from datasource".

My vendor_data2.json looks like this:
{"testing": {"cloud-init": "#cloud-config\npackage_upgrade: True\npackages:\n - htop"}}

Please let me know, if this issue is due to my JSON or an issue with how cloud-init handles vendor data. Since this pull request is fairly new, I am assuming not many people had the chance to test dynamic vendor data using cloud-init yet.

@andrewbogott
Copy link
Contributor Author

My vendor_data2.json looks like this:
{"testing": {"cloud-init": "#cloud-config\npackage_upgrade: True\npackages:\n - htop"}}

@mmahalwa, I believe in your nova.conf you are setting your vendordata target like this:

testing@http://

My understanding of this feature is that if you want the vendordata to be consumed by cloud-init you should instead direct it to the cloud-init target:

cloud-init@http://

Then you can remove the explicit cloud-init dictionary key in your datasource so that you get something that looks like

{"cloud-init": "#cloud-config\npackage_upgrade: True\npackages:\n - htop"}

I don't have a test platform handy to confirm this but I would expect that (or something very much like that) to work.

@mmahalwa
Copy link

mmahalwa commented Apr 19, 2021

@andrewbogott I can confirm that even after changing the json to {"cloud-init": "#cloud-config\npackage_upgrade: True\npackages:\n - htop"}, cloud-init 21.1 doesn't execute/parse the JSON. Even a simple YAML to echo a message doesn't work. However, the same JSON works in the case of Static JSON. I am not sure why this is happening, cloud-init just reads the x number of bytes but doesn't do anything with it. The error message from the cloud-init.log is same as I had mentioned earlier: "no vendordata2 from datasource".
Can it be because the current implementation only handles the vendordata in the metadata service and not in the config-drive? (I am using the config-drive)

Just for reference, this is how I am writing my response from my REST service to the POST request sent by Nova:

self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
self.wfile.write(json.dumps("#cloud-config\npackage_upgrade: True\npackages:\n - htop").encode(encoding='utf_8'))

I had mentioned here bugs.launchpad, why name@ might have a different meaning.
I may be wrong on this but, the intention of having the name field is just to have a name for the REST service from which the JSON came. For example, if I have several REST services to query from which I have to fetch vendor data.

From (https://specs.openstack.org/openstack/nova-specs/specs/newton/implemented/vendordata-reboot.html)
"Each REST microservice is configured by appending a new item to the list provided in the vendordata_dynamic_targets flag. This flag is composed of entries of the form:"

vendordata_dynamic_targets=name1@http://example.com,name2@http://example2.com

The name element for these microservices becomes the new key for the vendor_data2.json file like,

{
    "name1": {
        "cloud-init": "#cloud-config\n..."
    },
    "name2": {
        "cloud-init": "#cloud-config\n..."
    }
}

Please note I have taken the above example from the Nova specs mentioned earlier and extended it for 2 REST services. Now, if we consider your approach of having cloud-init as the outer key, then how are we going to differentiate b/w several REST services.

OddBloke pushed a commit that referenced this pull request Apr 19, 2021
In #777, we added 'vendordata2' and 'vendordata2_raw' attributes to
the DataSource class, but didn't use the upgrade framework to deal
with an unpickle after upgrade. This commit adds the necessary
upgrade code.

Additionally, added a smaller-scope upgrade test to our integration
tests that will be run on every CI run so we catch these issues
immediately in the future.

LP: #1922739
@frct1
Copy link

frct1 commented Apr 26, 2024

Almost year ago passed and seems still not resolved at all with vanilla openstack...
I'm developing open sourced project to allow host vendor_data that stored in Consul.
https://github.com/ib-systems/openstack-consul-dynamic-vendordata

nova-api is configured like next

vendordata_providers = DynamicJSON
vendordata_dynamic_targets = 'ocdv@http://10.10.10.10:8000/ocdv'

Vendor data returns next response:

{
  "ocdv": {
    "cloud-init": "#cloud-config\npackage_upgrade: True\npackages:\n - iotop"
  }
}

So everything is following OpenStack docs but no success due to cloud-init looks for "cloud-init" key in response, but no way to return string "#cloud-config" because from each service expected json reply. If you will try to return plain text from vendordata server (named as cloud-init to return as key cloud-init from vendordata) you will see next error in nova-api:

Error from dynamic vendordata service cloud-init at http://10.10.10.10:8000/ocdv: Expecting value: line 1 column 1 (char 0): json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) 

Did anybody found any workarounds on this ? Since feature is highly usefull it is not possible to use out-of-the-box due to misunderstand between cloud-init and openstack

@holmanb
Copy link
Member

holmanb commented Apr 26, 2024

Almost year ago passed and seems still not resolved at all with vanilla openstack...
I'm developing open sourced project to allow host vendor_data that stored in Consul.

@frct1 Is there a github issue filed for this? If not, then please file one. If so, please continue the conversation there. You can always link to old PRs if they are relevant. If there are bugs to be fixed or features to add, we're happy to collaborate to find solutions.

@frct1
Copy link

frct1 commented Apr 26, 2024

Almost year ago passed and seems still not resolved at all with vanilla openstack...
I'm developing open sourced project to allow host vendor_data that stored in Consul.

@frct1 Is there a github issue filed for this? If not, then please file one. If so, please continue the conversation there. You can always link to old PRs if they are relevant. If there are bugs to be fixed or features to add, we're happy to collaborate to find solutions.

Hello, @holmanb
It's done #5221

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants