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

cloud-config provided in OpenStack vendor data is ignored #5221

Closed
frct1 opened this issue Apr 26, 2024 · 6 comments
Closed

cloud-config provided in OpenStack vendor data is ignored #5221

frct1 opened this issue Apr 26, 2024 · 6 comments
Labels
enhancement New feature or request

Comments

@frct1
Copy link

frct1 commented Apr 26, 2024

Bug report

I'm developing open source project https://github.com/ib-systems/openstack-consul-dynamic-vendordata that will help to easily provide vendor data to OpenStack instances using Consul KV. This is useful when operator works with a lot of independent geographically distributed clouds but store instances vendor data in distributed Consul KV used by billing software for example that unifying managing all of regions in the same interface.

Current cloud-init behavior expect cloud-init key to present at vendor_data2.json to run provided #cloud-config (docs link). But providing #cloud-config as string is not possible in current vendor_data2.json DynamicJSON provider due to OpenStack Nova component expect JSON encoded response from vendor_data2.json provider.
Log line when i tried to return string contains #cloud-config from vendor data service.

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) 

raised at this line

I've created blueprint with possible workaround at Nova tracker but not sure that it will be accepted. Anyway this have to be solved after years of misconcerns.

Steps to reproduce the problem

Configure nova-api to request Dynamicvendor_data2.json

[api]
vendordata_providers=DynamicJSON
vendordata_dynamic_targets=testing@http://10.10.10.10:8888

Following nova specs vendor_data2,json will be returned in format as

{
  "testing": {
    "cloud-init": "#cloud-config\nhostname: ocdvworks",
    "region":"eu-1"
  }
}

Current dynamic vendordata on Consul KV is store in next format:

{
    "cloud-init": "#cloud-config\nhostname: ocdvworks", 
    "region":"eu-1" // ignore region here, this is used internally, will be ignored in next samples
}

Following OpenStack specs there is could be a lot of different as called vendor data providers that could be used for licensing, software metadata and so on.

it works, but...

I've changed vendordata_dynamic_targets to vendordata_dynamic_targets=cloud-init@http://10.10.10.10:8888 in order to have cloud-init key in vendor_data2.json and then monkey-patched nova-api's metadata code inside docker container at this line to return plain text. So now i have vendor_data2.json looks like

{
    "cloud-init": "#cloud-config\nhostname: ocdvworks" // returned as plain text from Consul KV that contain just #cloud-config, not json
}

then as result cloud-init runs provided #cloud-config absolutely correct with no issues at all.

I would like to propose possible solution for cloud-init to merge all of #cloud-config provided from all of providers and then continue basic behavior (override with user-data if provided or go ahead in processing pipeline). In case only one key is presented in vendor_data2.json like:

{
  "testing": {
    "cloud-init": "#cloud-config\nhostname: ocdvworks"
  }
}

I guess this is most used case for vendors) simply extract #cloud-config from cloud-init key (if provided).

Environment details

  • Cloud-init version: 21.3, 24.1.3 tried, no success
  • Operating System Distribution: Ubuntu
  • Cloud provider, platform or installer type: OpenStack Zed (vanilla)

cloud-init logs

None. Only log seen when JSON provided within cloud-init key in vendor_data2.json with "wrong format message".

refs

Openstack's vendor_data2.json is not handled
openstack: read the dynamic metadata group vendor_data2.json

@frct1 frct1 added bug Something isn't working correctly new An issue that still needs triage labels Apr 26, 2024
@holmanb holmanb added enhancement New feature or request and removed bug Something isn't working correctly labels Apr 29, 2024
@holmanb
Copy link
Member

holmanb commented Apr 29, 2024

Current cloud-init behavior expect cloud-init key to present at vendor_data2.json to run provided #cloud-config (docs link). But providing #cloud-config as string is not possible in current vendor_data2.json DynamicJSON provider due to OpenStack Nova component expect JSON encoded response from vendor_data2.json provider.
Log line when i tried to return string contains #cloud-config from vendor data service.

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)

raised at this line

I've created blueprint with possible workaround at Nova tracker but not sure that it will be accepted. Anyway this have to be solved after years of misconcerns.

This sounds like a bug in a Nova feature to me (or maybe even just a Nova feature request). I'm not sure what cloud-init is supposed to do about this.

@holmanb
Copy link
Member

holmanb commented Apr 29, 2024

Unless I misunderstand and cloud-init is actually unable to use the cloud-init key in vendor_data2.json that is provided by Nova, I'm inclined to close this as "won't fix", since cloud-init appears to be working as intended.

@frct1 Am I missing something?

@holmanb holmanb removed the new An issue that still needs triage label Apr 29, 2024
@frct1
Copy link
Author

frct1 commented Apr 29, 2024

This sounds like a bug in a Nova feature to me (or maybe even just a Nova feature request). I'm not sure what cloud-init is supposed to do about this.

Same thing. Since cloud-init works fine if cloud-init key in vendor_data2.json is presented as string it works as expected but there is discrepancy between Nova docs and cloud-init logic 🤷‍♂️
I've already created proposal to Nova to let vendor_data2.json JSON object contain cloud-init key as plain string.

@SeanMooney
Copy link

reviewing this form a nova perspective the cloud-init integration is not compatible with nova implemation and this looks to be a bug in cloud-init

nova's implementation of vendor data expect the content of sopenstack/2016-10-06/vendor_data2.json

to be a single json object containing a key per dynamic vendor data service with the content of the respocne for that backend being a valid json respocne

sopenstack/2016-10-06/vendor_data2.json

in this case we have two vender data backedn

vendordata_dynamic_targets=[
'testing@http://127.0.0.1:123',
'hamster@http://127.0.0.1:123'
],

when we parst vendor_data2.json
we expect to have two keys in the reultant object testing and hamster
and each is a dict containing addition keys

that means we would expect the vendor data to look like

{
"testing": {
"cloud-init": "#cloud-config\nhostname: ocdvworks",
"region":"eu-1"
}
}

not

{
"cloud-init": "#cloud-config\nhostname: ocdvworks",
"region":"eu-1"
}

so https://cloudinit.readthedocs.io/en/latest/reference/datasources/openstack.html#vendor-data is not compatible with OpenStack and never has been as far as i can tell at a quick glance.

@SeanMooney
Copy link

just to clarify

nova provide the following format in the vendor data

{
"<provider 1>": {<provider 1 repsonce as nested dict>},
"<provider 2>": {<provider 2 repsonce as nested dict>}
}

i.e.

{
  "testing": {
    "cloud-init": "#cloud-config\nhostname: ocdvworks",
    "region":"eu-1"
  }
}

we require vendor data backends to provide a json response
which we then embed in the vendor_data files keyed by the backend

so form my perspective there is a bug in at least the Cloudinit docs as the example provided in
https://cloudinit.readthedocs.io/en/latest/reference/datasources/openstack.html#vendor-data

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

is a valid reponce form a backend but its not a valid example fo the content of vendor_data2.json as produced by nova.

it would look like this

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

supporting a different format that allowed adding content directly to the root object
would be a file format change as consumer of the file would not be able to rely on the deserialised json being a dict of dicts

there may be one way to hack this to work today
if you named the backend 'cloud-init'
https://docs.openstack.org/nova/latest/configuration/config.html#api.vendordata_dynamic_targets
i.e.

[API] 
vendordata_dynamic_targets=['cloud-init:string@http://127.0.0.1:123']

and the backend provider returned just the cloud-init content
so literally

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

then that might work
a single string is trecnially a valid json value

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

then it might work even if that is technically not intended to work today

@frct1
Copy link
Author

frct1 commented May 2, 2024

@SeanMooney suggested a possible way to hack this while explicit support on provider data type is not implemented.

from oslo_serialization import jsonutils
res = "#cloud-config\n..."
jsonutils.dumps(res)

Following this way cloud-config returned as a raw string and counts as valid JSON.

@github-actions github-actions bot added the Stale label Sep 12, 2024
@aciba90 aciba90 removed the Stale label Oct 3, 2024
@frct1 frct1 closed this as completed Oct 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants