Skip to content

Commit

Permalink
Use /run/cloud-init semaphore to determine if weve already applied ne…
Browse files Browse the repository at this point in the history
…tworking config this boot
  • Loading branch information
TheRealFalcon committed Apr 28, 2021
1 parent 9fb6353 commit 399483a
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 23 deletions.
1 change: 1 addition & 0 deletions cloudinit/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class EventType(Enum):

BOOT = "boot"
BOOT_NEW_INSTANCE = "boot-new-instance"
BOOT_LEGACY = "boot-legacy"

def __str__(self): # pylint: disable=invalid-str-returned
return self.value
Expand Down
7 changes: 4 additions & 3 deletions cloudinit/sources/DataSourceAzure.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ class DataSourceAzure(sources.DataSource):
# Regenerate network config new_instance boot and every boot
default_update_events = {EventScope.NETWORK: {
EventType.BOOT_NEW_INSTANCE,
EventType.BOOT
EventType.BOOT,
EventType.BOOT_LEGACY
}}

_negotiated = False
Expand Down Expand Up @@ -2133,8 +2134,8 @@ def maybe_remove_ubuntu_network_config_scripts(paths=None):
LOG.info(
'Removing Ubuntu extended network scripts because'
' cloud-init updates Azure network configuration on the'
' following event: %s.',
EventType.BOOT)
' following events: %s.',
[EventType.BOOT.value, EventType.BOOT_LEGACY.value])
logged = True
if os.path.isdir(path):
util.del_dir(path)
Expand Down
2 changes: 2 additions & 0 deletions cloudinit/sources/DataSourceEc2.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ def network_config(self):
self.default_update_events)
self.default_update_events[EventScope.NETWORK].add(
EventType.BOOT)
self.default_update_events[EventScope.NETWORK].add(
EventType.BOOT_LEGACY)
else:
LOG.warning("Metadata 'network' key not valid: %s.", net_md)
self._network_config = result
Expand Down
3 changes: 2 additions & 1 deletion cloudinit/sources/DataSourceRbxCloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ class DataSourceRbxCloud(sources.DataSource):
dsname = "RbxCloud"
default_update_events = {EventScope.NETWORK: {
EventType.BOOT_NEW_INSTANCE,
EventType.BOOT
EventType.BOOT,
EventType.BOOT_LEGACY
}}

def __init__(self, sys_cfg, distro, paths):
Expand Down
6 changes: 5 additions & 1 deletion cloudinit/sources/DataSourceScaleway.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ def query_data_api(api_type, api_address, retries, timeout):
class DataSourceScaleway(sources.DataSource):
dsname = "Scaleway"
default_update_events = {
EventScope.NETWORK: {EventType.BOOT_NEW_INSTANCE, EventType.BOOT}
EventScope.NETWORK: {
EventType.BOOT_NEW_INSTANCE,
EventType.BOOT,
EventType.BOOT_LEGACY
}
}

def __init__(self, sys_cfg, distro, paths):
Expand Down
3 changes: 2 additions & 1 deletion cloudinit/sources/DataSourceSmartOS.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ class DataSourceSmartOS(sources.DataSource):
md_client = sources.UNSET
default_update_events = {EventScope.NETWORK: {
EventType.BOOT_NEW_INSTANCE,
EventType.BOOT
EventType.BOOT,
EventType.BOOT_LEGACY
}}

def __init__(self, sys_cfg, distro, paths):
Expand Down
3 changes: 2 additions & 1 deletion cloudinit/sources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,10 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta):
supported_update_events = {EventScope.NETWORK: {
EventType.BOOT_NEW_INSTANCE,
EventType.BOOT,
EventType.BOOT_LEGACY,
}}
default_update_events = {EventScope.NETWORK: {
EventType.BOOT_NEW_INSTANCE
EventType.BOOT_NEW_INSTANCE,
}}

# N-tuple listing default values for any metadata-related class
Expand Down
40 changes: 24 additions & 16 deletions cloudinit/stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from typing import Dict, Set

from cloudinit.settings import (
FREQUENCIES, CLOUD_CONFIG, PER_INSTANCE, RUN_CLOUD_CONFIG)
FREQUENCIES, CLOUD_CONFIG, PER_INSTANCE, PER_ONCE, RUN_CLOUD_CONFIG)

from cloudinit import handlers

Expand Down Expand Up @@ -62,7 +62,9 @@ def __init__(self, ds_deps=None, reporter=None):
self.datasource = NULL_DATA_SOURCE
self.ds_restored = False
self._previous_iid = None
self.boot_type = EventType.BOOT
self.network_semaphore = helpers.FileSemaphores(
self.paths.get_runpath('sem'))
self.network_semaphore_args = ('apply_network_config', PER_ONCE)

if reporter is None:
reporter = events.ReportEventStack(
Expand Down Expand Up @@ -124,6 +126,7 @@ def paths(self):

def _initial_subdirs(self):
c_dir = self.paths.cloud_dir
run_dir = self.paths.run_dir
initial_dirs = [
c_dir,
os.path.join(c_dir, 'scripts'),
Expand All @@ -136,6 +139,7 @@ def _initial_subdirs(self):
os.path.join(c_dir, 'handlers'),
os.path.join(c_dir, 'sem'),
os.path.join(c_dir, 'data'),
os.path.join(run_dir, 'sem'),
]
return initial_dirs

Expand Down Expand Up @@ -325,9 +329,6 @@ def _reflect_cur_instance(self):
util.write_file(os.path.join(dp, 'previous-instance-id'),
"%s\n" % (previous_iid))

if self.is_new_instance():
self.boot_type = EventType.BOOT_NEW_INSTANCE

self._write_to_cache()
# Ensure needed components are regenerated
# after change of instance which may cause
Expand Down Expand Up @@ -745,7 +746,6 @@ def update_event_enabled(
else:
scopes = [scope]
scope_values = [s.value for s in scopes]
LOG.debug('Possible scopes for this event: %s', scope_values)

for evt_scope in scopes:
if event_source_type in allowed.get(evt_scope, []):
Expand All @@ -764,6 +764,9 @@ def _apply_netcfg_names(self, netcfg):
except Exception as e:
LOG.warning("Failed to rename devices: %s", e)

def _network_already_configured(self) -> bool:
return self.network_semaphore.has_run(*self.network_semaphore_args)

def apply_network_config(self, bring_up):
"""Apply the network config.
Expand All @@ -775,22 +778,24 @@ def apply_network_config(self, bring_up):
LOG.info("network config is disabled by %s", src)
return

def _boot_event_enabled_and_metadata_updated():
def event_enabled_and_metadata_updated(event_type):
return self.update_event_enabled(
EventType.BOOT, scope=EventScope.NETWORK
) and self.datasource.update_metadata_if_supported(
[EventType.BOOT]
)
event_type, scope=EventScope.NETWORK
) and self.datasource.update_metadata_if_supported([event_type])

def should_run_on_boot_event():
return (not self._network_already_configured() and
event_enabled_and_metadata_updated(EventType.BOOT))

if (
self.datasource is not NULL_DATA_SOURCE and
self.boot_type != EventType.BOOT_NEW_INSTANCE and
not _boot_event_enabled_and_metadata_updated()
not self.is_new_instance() and
not should_run_on_boot_event() and
not event_enabled_and_metadata_updated(EventType.BOOT_LEGACY)
):
LOG.debug(
"No network config applied. Neither a new instance"
" nor datasource network update on '%s' event",
self.boot_type)
" nor datasource network update allowed")
# nothing new, but ensure proper names
self._apply_netcfg_names(netcfg)
return
Expand All @@ -807,8 +812,11 @@ def _boot_event_enabled_and_metadata_updated():
# rendering config
LOG.info("Applying network configuration from %s bringup=%s: %s",
src, bring_up, netcfg)

try:
return self.distro.apply_network_config(netcfg, bring_up=bring_up)
with self.network_semaphore.lock(*self.network_semaphore_args):
return self.distro.apply_network_config(
netcfg, bring_up=bring_up)
except net.RendererNotFoundError as e:
LOG.error("Unable to render networking. Network config is "
"likely broken: %s", e)
Expand Down

0 comments on commit 399483a

Please sign in to comment.