95-juju-proxy-settings does not appear which means that this bootcmd never runs and the file never gets created.
3) If I move the bootcmd to write out the proxy file (95-juju-proxy-settings) to the top of the list of bootcmds (https://paste.ubuntu.com/p/tHMyrNWQYK/
) and run `rm -r /var/lib/cloud/instances/juju-6d9aac-3-lxd-3/ ; reboot`, then I get 95-juju-proxy-settings at the right place and time (crtime reported via debugfs is before bootcmd stage ends).
In other words, there is something wrong either in the format of one of the bootcmds or the way cloud-init processes this list of commands.
The behavior in #16 is due to the fact that the bootcmd related to writing 95-juju-proxy-settings never runs while a machine agent has its own code (in proxyupdater goroutine) to write 95-juju-proxy-settings (which obviously happens after bootcmd finishes):
I also explored if bootcmd code could be doing work with child processes incorrectly but it does wait for a child process to exit by calling "communicate" and this means that all file descriptors will be closed by the time parent gets unblocked (http://man7.org/linux/man-pages/man2/exit.2.html "... _exit() does close open file descriptors ...":
Back to the behavior in #16. I think there is something wrong in how bootcmd is generated by Juju or processed by cloud-init.
1) LXD container user.user-data config: https:/ /paste. ubuntu. com/p/cXn75hS8J 9/ cloud/seed/ nocloud- net/user- data https:/ /paste. ubuntu. com/p/6B4KXJ6xv d/
2) user-data generated out of it /var/lib/
see https:/ /github. com/lxc/ lxd/blob/ master/ doc/cloud- init.md
Notice that the command to write out /etc/apt/ apt.conf. d/95-juju- proxy-settings is the last bootcmd in both (1) and (2).
3) if I disable and mask Juju services
sudo systemctl mask jujud-unit- openstack- dashboard- 4.service openstack- dashboard- 4.service
sudo systemctl disable jujud-unit-
sudo systemctl disable jujud-machine- 3-lxd-3. service 3-lxd-3. service
sudo systemctl mask jujud-machine-
And then do
rm /etc/apt/ apt.conf. d/95-juju- proxy-settings
reboot
95-juju- proxy-settings does not appear which means that this bootcmd never runs and the file never gets created.
3) If I move the bootcmd to write out the proxy file (95-juju- proxy-settings) to the top of the list of bootcmds (https:/ /paste. ubuntu. com/p/tHMyrNWQY K/ cloud/instances /juju-6d9aac- 3-lxd-3/ ; reboot`, then I get 95-juju- proxy-settings at the right place and time (crtime reported via debugfs is before bootcmd stage ends).
) and run `rm -r /var/lib/
In other words, there is something wrong either in the format of one of the bootcmds or the way cloud-init processes this list of commands.
The behavior in #16 is due to the fact that the bootcmd related to writing 95-juju- proxy-settings never runs while a machine agent has its own code (in proxyupdater goroutine) to write 95-juju- proxy-settings (which obviously happens after bootcmd finishes):
https:/ /github. com/juju/ juju/blob/ juju-2. 5.0/worker/ proxyupdater/ proxyupdater. go#L250- L261 proxy-settings"
AptProxyConfigFile = AptConfigDirectory + "/95-juju-
https:/ /github. com/juju/ packaging/ blob/ba21344fff 207f4fa06b0a08b ac386b179a2e6a1 /config/ apt_constants. go#L37- L40 ProxyConfigCont ents(w. aptProxy) + "\n" WriteFile( config. AptProxyConfigF ile, []byte(content), 0644)
content := paccmder.
err = ioutil.
I also explored if bootcmd code could be doing work with child processes incorrectly but it does wait for a child process to exit by calling "communicate" and this means that all file descriptors will be closed by the time parent gets unblocked (http:// man7.org/ linux/man- pages/man2/ exit.2. html "... _exit() does close open file descriptors ...":
https:/ /github. com/cloud- init/cloud- init/blob/ ubuntu/ 18.4-0ubuntu1_ 18.04.1/ cloudinit/ config/ cc_bootcmd. py#L79- L102
util. subp(cmd, env=env, capture=False)
def handle(name, cfg, cloud, log, _args):
# ...
cmd = ['/bin/sh', tmpf.name]
# ...
https:/ /github. com/cloud- init/cloud- init/blob/ ubuntu/ 18.4-0ubuntu1_ 18.04.1/ cloudinit/ util.py# L1919-L2033
combine_ capture= False, shell=False,
logstring= False, decode="replace", target=None, update_env=None,
status_ cb=None) :
def subp(args, data=None, rcs=None, env=None, capture=True,
# ...
stdin = None
stdout = None
stderr = None
if capture:
stdout = subprocess.PIPE
stderr = subprocess.PIPE
sp = subprocess. Popen(bytes_ args, stdout=stdout,
stderr= stderr, stdin=stdin,
env=env, shell=shell) data)
(out, err) = sp.communicate(