← Back to team overview

cloud-init-dev team mailing list archive

[Merge] lp:~harlowja/cloud-init/notify-on-reload into lp:cloud-init

 

Joshua Harlow has proposed merging lp:~harlowja/cloud-init/notify-on-reload into lp:cloud-init.

Commit message:
Use a notify/subscribe model for configuration/distro reloading.
  
  Instead of the previous way where we reached into the datasource
  object and messed with its properties its cleaner to create a 
  tiny set of functions that can be used to notify others of changes
  and let them use those changes as they wish. So instead of messing
  with the datasource properties, just notify it something has changed
  and have the datasource modify itself instead.

Requested reviews:
  cloud init development team (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~harlowja/cloud-init/notify-on-reload/+merge/140365
-- 
https://code.launchpad.net/~harlowja/cloud-init/notify-on-reload/+merge/140365
Your team cloud init development team is requested to review the proposed merge of lp:~harlowja/cloud-init/notify-on-reload into lp:cloud-init.
=== modified file 'cloudinit/sources/__init__.py'
--- cloudinit/sources/__init__.py	2012-11-12 17:26:49 +0000
+++ cloudinit/sources/__init__.py	2012-12-18 07:45:25 +0000
@@ -52,16 +52,24 @@
         self.userdata = None
         self.metadata = None
         self.userdata_raw = None
-        name = util.obj_name(self)
-        if name.startswith(DS_PREFIX):
-            name = name[len(DS_PREFIX):]
+        self.name = util.obj_name(self)
+        if self.name.startswith(DS_PREFIX):
+            self.name = self.name[len(DS_PREFIX):]
         self.ds_cfg = util.get_cfg_by_path(self.sys_cfg,
-                                          ("datasource", name), {})
+                                          ("datasource", self.name), {})
         if not ud_proc:
             self.ud_proc = ud.UserDataProcessor(self.paths)
         else:
             self.ud_proc = ud_proc
 
+    def notify_reloaded(self, distro, system_config, _cloud_config):
+        if system_config:
+            self.sys_cfg = system_config
+            self.ds_cfg = util.get_cfg_by_path(self.sys_cfg,
+                                               ("datasource", self.name), {})
+        if distro:
+            self.distro = distro
+
     def get_userdata(self, apply_filter=False):
         if self.userdata is None:
             self.userdata = self.ud_proc.process(self.get_userdata_raw())

=== modified file 'cloudinit/stages.py'
--- cloudinit/stages.py	2012-12-17 13:41:11 +0000
+++ cloudinit/stages.py	2012-12-18 07:45:25 +0000
@@ -62,6 +62,7 @@
         self._distro = None
         # Changed only when a fetch occurs
         self.datasource = NULL_DATA_SOURCE
+        self.notify_listeners = []
 
     def _reset(self, reset_ds=False):
         # Recreated on access
@@ -74,20 +75,24 @@
     @property
     def distro(self):
         if not self._distro:
-            # Try to find the right class to use
+            # Try to find the right class to use  
             system_config = self._extract_cfg('system')
             distro_name = system_config.pop('distro', 'ubuntu')
             distro_cls = distros.fetch(distro_name)
             LOG.debug("Using distro class %s", distro_cls)
             self._distro = distro_cls(distro_name, system_config, self.paths)
-            # If we have an active datasource we need to adjust
-            # said datasource and move its distro/system config
-            # from whatever it was to a new set...
-            if self.datasource is not NULL_DATA_SOURCE:
-                self.datasource.distro = self._distro
-                self.datasource.sys_cfg = system_config
+            # Let any listener know that we have reloaded
+            self._notify_reloaded(self._distro, system_config, self.cfg)
         return self._distro
 
+    def add_reloaded_listener(self, listener):
+        if listener not in self.notify_listeners:
+            self.notify_listeners.append(listener)
+
+    def _notify_reloaded(self, distro, system_config, cloud_config):
+        for i in self.notify_listeners:
+            i.notify_reloaded(distro, system_config, cloud_config)
+
     @property
     def cfg(self):
         return self._extract_cfg('restricted')
@@ -161,9 +166,11 @@
         # None check so that we don't keep on re-loading if empty
         if self._cfg is None:
             self._cfg = self._read_cfg(extra_fns)
-            # LOG.debug("Loaded 'init' config %s", self._cfg)
 
     def _read_cfg(self, extra_fns):
+        # A no config path object is used since at the point where this
+        # function is called, it is loading the configuration to be so
+        # it doesn't have access to any previous configuration...
         no_cfg_paths = helpers.Paths({}, self.datasource)
         merger = helpers.ConfigMerger(paths=no_cfg_paths,
                                       datasource=self.datasource,
@@ -235,8 +242,10 @@
                                                pkg_list)
             LOG.debug("Loaded datasource %s - %s", dsname, ds)
         self.datasource = ds
-        # Ensure we adjust our path members datasource
-        # now that we have one (thus allowing ipath to be used)
+        # Automatically add the loaded datasource to the reload notification
+        # listener list so that it gets notified when configuration and distro
+        # reloads happen...
+        self.add_reloaded_listener(ds)
         self._reset()
         return ds
 
@@ -420,6 +429,7 @@
         #
         # They will be recreated on future access...
         self._reset()
+
         # Note(harlowja): the 'active' datasource will have
         # references to the previous config, distro, paths
         # objects before the load of the userdata happened,


Follow ups