From 2e51e2efc292870479a7b972c7ebc9ceac85da6f Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Mon, 27 Aug 2012 20:51:00 -0700 Subject: For the userdata 'post-filtering' add in a new folder that can contain filters that serve this purpose only and add in the initial launch-index filter and replace the code in the datasource class that previously did this. --- cloudinit/filters/__init__.py | 21 +++++++++++++ cloudinit/filters/launch_index.py | 63 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 cloudinit/filters/__init__.py create mode 100644 cloudinit/filters/launch_index.py (limited to 'cloudinit/filters') diff --git a/cloudinit/filters/__init__.py b/cloudinit/filters/__init__.py new file mode 100644 index 00000000..da124641 --- /dev/null +++ b/cloudinit/filters/__init__.py @@ -0,0 +1,21 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2012 Canonical Ltd. +# Copyright (C) 2012 Hewlett-Packard Development Company, L.P. +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Scott Moser +# Author: Juerg Haefliger +# Author: Joshua Harlow +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/cloudinit/filters/launch_index.py b/cloudinit/filters/launch_index.py new file mode 100644 index 00000000..b9e108c4 --- /dev/null +++ b/cloudinit/filters/launch_index.py @@ -0,0 +1,63 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2012 Canonical Ltd. +# Copyright (C) 2012 Hewlett-Packard Development Company, L.P. +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Scott Moser +# Author: Juerg Haefliger +# Author: Joshua Harlow +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import copy + +from cloudinit import log as logging +from cloudinit import user_data as ud +from cloudinit import util + +LOG = logging.getLogger(__name__) + + +class Filter(object): + def __init__(self, wanted_idx, allow_none=True): + self.wanted_idx = wanted_idx + self.allow_none = allow_none + + def _select(self, message): + if ud.is_skippable(message): + return False + msg_idx = message.get('Launch-Index', None) + if self.allow_none and msg_idx is None: + return True + msg_idx = util.safe_int(msg_idx) + if msg_idx != self.wanted_idx: + return False + return True + + def apply(self, base_message): + if not base_message.is_multipart() or self.wanted_idx is None: + return base_message + prev_msgs = base_message.get_payload(decode=False) + to_attach = [] + for sub_msg in base_message.walk(): + if self._select(sub_msg): + to_attach.append(sub_msg) + if len(prev_msgs) != len(to_attach): + LOG.debug(("Discarding %s multipart messages " + "which do not match launch index %s"), + (len(prev_msgs) - len(to_attach)), self.wanted_idx) + filtered_msg = copy.deepcopy(base_message) + filtered_msg.set_payload(to_attach) + filtered_msg[ud.ATTACHMENT_FIELD] = str(len(to_attach)) + return filtered_msg -- cgit v1.2.3 From ff60020fa3d8e457cf9d1d543af9193376bf598c Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Wed, 29 Aug 2012 10:52:44 -0700 Subject: Don't use walk and handle the walking ourselves to ensure that we recreate all child messages correctly if they also contain submessages, ensuring that we don't flatten the message list when we previously used walk. --- cloudinit/filters/launch_index.py | 44 +++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'cloudinit/filters') diff --git a/cloudinit/filters/launch_index.py b/cloudinit/filters/launch_index.py index b9e108c4..4299fb46 100644 --- a/cloudinit/filters/launch_index.py +++ b/cloudinit/filters/launch_index.py @@ -35,8 +35,6 @@ class Filter(object): self.allow_none = allow_none def _select(self, message): - if ud.is_skippable(message): - return False msg_idx = message.get('Launch-Index', None) if self.allow_none and msg_idx is None: return True @@ -45,19 +43,33 @@ class Filter(object): return False return True - def apply(self, base_message): - if not base_message.is_multipart() or self.wanted_idx is None: - return base_message - prev_msgs = base_message.get_payload(decode=False) - to_attach = [] - for sub_msg in base_message.walk(): - if self._select(sub_msg): - to_attach.append(sub_msg) - if len(prev_msgs) != len(to_attach): + def _do_filter(self, message): + # Don't use walk() here since we want to do the reforming of the + # messages ourselves and not flatten the message listings... + if not self._select(message): + return None + if message.is_multipart(): + # Recreate it and its child messages + prev_msgs = message.get_payload(decode=False) + new_msgs = [] + discarded = 0 + for m in prev_msgs: + m = self._do_filter(m) + if m is not None: + new_msgs.append(m) + else: + discarded += 1 LOG.debug(("Discarding %s multipart messages " "which do not match launch index %s"), - (len(prev_msgs) - len(to_attach)), self.wanted_idx) - filtered_msg = copy.deepcopy(base_message) - filtered_msg.set_payload(to_attach) - filtered_msg[ud.ATTACHMENT_FIELD] = str(len(to_attach)) - return filtered_msg + discarded, self.wanted_idx) + new_message = copy.copy(message) + new_message.set_payload(new_msgs) + new_message[ud.ATTACHMENT_FIELD] = str(len(new_msgs)) + return new_message + else: + return copy.copy(message) + + def apply(self, root_message): + if self.wanted_idx is None: + return root_message + return self._do_filter(root_message) -- cgit v1.2.3