diff options
Diffstat (limited to 'cloudinit/distros/parsers')
-rw-r--r-- | cloudinit/distros/parsers/__init__.py | 28 | ||||
-rw-r--r-- | cloudinit/distros/parsers/hostname.py | 88 | ||||
-rw-r--r-- | cloudinit/distros/parsers/hosts.py | 92 | ||||
-rw-r--r-- | cloudinit/distros/parsers/resolv_conf.py | 169 | ||||
-rw-r--r-- | cloudinit/distros/parsers/sys_conf.py | 113 |
5 files changed, 0 insertions, 490 deletions
diff --git a/cloudinit/distros/parsers/__init__.py b/cloudinit/distros/parsers/__init__.py deleted file mode 100644 index 1c413eaa..00000000 --- a/cloudinit/distros/parsers/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow <harlowja@yahoo-inc.com> -# -# 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 <http://www.gnu.org/licenses/>. - - -def chop_comment(text, comment_chars): - comment_locations = [text.find(c) for c in comment_chars] - comment_locations = [c for c in comment_locations if c != -1] - if not comment_locations: - return (text, '') - min_comment = min(comment_locations) - before_comment = text[0:min_comment] - comment = text[min_comment:] - return (before_comment, comment) diff --git a/cloudinit/distros/parsers/hostname.py b/cloudinit/distros/parsers/hostname.py deleted file mode 100644 index efb185d4..00000000 --- a/cloudinit/distros/parsers/hostname.py +++ /dev/null @@ -1,88 +0,0 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow <harlowja@yahoo-inc.com> -# -# 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 <http://www.gnu.org/licenses/>. - -from six import StringIO - -from cloudinit.distros.parsers import chop_comment - - -# Parser that knows how to work with /etc/hostname format -class HostnameConf(object): - def __init__(self, text): - self._text = text - self._contents = None - - def parse(self): - if self._contents is None: - self._contents = self._parse(self._text) - - def __str__(self): - self.parse() - contents = StringIO() - for (line_type, components) in self._contents: - if line_type == 'blank': - contents.write("%s\n" % (components[0])) - elif line_type == 'all_comment': - contents.write("%s\n" % (components[0])) - elif line_type == 'hostname': - (hostname, tail) = components - contents.write("%s%s\n" % (hostname, tail)) - # Ensure trailing newline - contents = contents.getvalue() - if not contents.endswith("\n"): - contents += "\n" - return contents - - @property - def hostname(self): - self.parse() - for (line_type, components) in self._contents: - if line_type == 'hostname': - return components[0] - return None - - def set_hostname(self, your_hostname): - your_hostname = your_hostname.strip() - if not your_hostname: - return - self.parse() - replaced = False - for (line_type, components) in self._contents: - if line_type == 'hostname': - components[0] = str(your_hostname) - replaced = True - if not replaced: - self._contents.append(('hostname', [str(your_hostname), ''])) - - def _parse(self, contents): - entries = [] - hostnames_found = set() - for line in contents.splitlines(): - if not len(line.strip()): - entries.append(('blank', [line])) - continue - (head, tail) = chop_comment(line.strip(), '#') - if not len(head): - entries.append(('all_comment', [line])) - continue - entries.append(('hostname', [head, tail])) - hostnames_found.add(head) - if len(hostnames_found) > 1: - raise IOError("Multiple hostnames (%s) found!" - % (hostnames_found)) - return entries diff --git a/cloudinit/distros/parsers/hosts.py b/cloudinit/distros/parsers/hosts.py deleted file mode 100644 index 3c5498ee..00000000 --- a/cloudinit/distros/parsers/hosts.py +++ /dev/null @@ -1,92 +0,0 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow <harlowja@yahoo-inc.com> -# -# 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 <http://www.gnu.org/licenses/>. - -from six import StringIO - -from cloudinit.distros.parsers import chop_comment - - -# See: man hosts -# or http://unixhelp.ed.ac.uk/CGI/man-cgi?hosts -# or http://tinyurl.com/6lmox3 -class HostsConf(object): - def __init__(self, text): - self._text = text - self._contents = None - - def parse(self): - if self._contents is None: - self._contents = self._parse(self._text) - - def get_entry(self, ip): - self.parse() - options = [] - for (line_type, components) in self._contents: - if line_type == 'option': - (pieces, _tail) = components - if len(pieces) and pieces[0] == ip: - options.append(pieces[1:]) - return options - - def del_entries(self, ip): - self.parse() - n_entries = [] - for (line_type, components) in self._contents: - if line_type != 'option': - n_entries.append((line_type, components)) - continue - else: - (pieces, _tail) = components - if len(pieces) and pieces[0] == ip: - pass - elif len(pieces): - n_entries.append((line_type, list(components))) - self._contents = n_entries - - def add_entry(self, ip, canonical_hostname, *aliases): - self.parse() - self._contents.append(('option', - ([ip, canonical_hostname] + list(aliases), ''))) - - def _parse(self, contents): - entries = [] - for line in contents.splitlines(): - if not len(line.strip()): - entries.append(('blank', [line])) - continue - (head, tail) = chop_comment(line.strip(), '#') - if not len(head): - entries.append(('all_comment', [line])) - continue - entries.append(('option', [head.split(None), tail])) - return entries - - def __str__(self): - self.parse() - contents = StringIO() - for (line_type, components) in self._contents: - if line_type == 'blank': - contents.write("%s\n" % (components[0])) - elif line_type == 'all_comment': - contents.write("%s\n" % (components[0])) - elif line_type == 'option': - (pieces, tail) = components - pieces = [str(p) for p in pieces] - pieces = "\t".join(pieces) - contents.write("%s%s\n" % (pieces, tail)) - return contents.getvalue() diff --git a/cloudinit/distros/parsers/resolv_conf.py b/cloudinit/distros/parsers/resolv_conf.py deleted file mode 100644 index 2ed13d9c..00000000 --- a/cloudinit/distros/parsers/resolv_conf.py +++ /dev/null @@ -1,169 +0,0 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow <harlowja@yahoo-inc.com> -# -# 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 <http://www.gnu.org/licenses/>. - -from six import StringIO - -from cloudinit import util - -from cloudinit.distros.parsers import chop_comment - - -# See: man resolv.conf -class ResolvConf(object): - def __init__(self, text): - self._text = text - self._contents = None - - def parse(self): - if self._contents is None: - self._contents = self._parse(self._text) - - @property - def nameservers(self): - self.parse() - return self._retr_option('nameserver') - - @property - def local_domain(self): - self.parse() - dm = self._retr_option('domain') - if dm: - return dm[0] - return None - - @property - def search_domains(self): - self.parse() - current_sds = self._retr_option('search') - flat_sds = [] - for sdlist in current_sds: - for sd in sdlist.split(None): - if sd: - flat_sds.append(sd) - return flat_sds - - def __str__(self): - self.parse() - contents = StringIO() - for (line_type, components) in self._contents: - if line_type == 'blank': - contents.write("\n") - elif line_type == 'all_comment': - contents.write("%s\n" % (components[0])) - elif line_type == 'option': - (cfg_opt, cfg_value, comment_tail) = components - line = "%s %s" % (cfg_opt, cfg_value) - if len(comment_tail): - line += comment_tail - contents.write("%s\n" % (line)) - return contents.getvalue() - - def _retr_option(self, opt_name): - found = [] - for (line_type, components) in self._contents: - if line_type == 'option': - (cfg_opt, cfg_value, _comment_tail) = components - if cfg_opt == opt_name: - found.append(cfg_value) - return found - - def add_nameserver(self, ns): - self.parse() - current_ns = self._retr_option('nameserver') - new_ns = list(current_ns) - new_ns.append(str(ns)) - new_ns = util.uniq_list(new_ns) - if len(new_ns) == len(current_ns): - return current_ns - if len(current_ns) >= 3: - # Hard restriction on only 3 name servers - raise ValueError(("Adding %r would go beyond the " - "'3' maximum name servers") % (ns)) - self._remove_option('nameserver') - for n in new_ns: - self._contents.append(('option', ['nameserver', n, ''])) - return new_ns - - def _remove_option(self, opt_name): - - def remove_opt(item): - line_type, components = item - if line_type != 'option': - return False - (cfg_opt, _cfg_value, _comment_tail) = components - if cfg_opt != opt_name: - return False - return True - - new_contents = [] - for c in self._contents: - if not remove_opt(c): - new_contents.append(c) - self._contents = new_contents - - def add_search_domain(self, search_domain): - flat_sds = self.search_domains - new_sds = list(flat_sds) - new_sds.append(str(search_domain)) - new_sds = util.uniq_list(new_sds) - if len(flat_sds) == len(new_sds): - return new_sds - if len(flat_sds) >= 6: - # Hard restriction on only 6 search domains - raise ValueError(("Adding %r would go beyond the " - "'6' maximum search domains") % (search_domain)) - s_list = " ".join(new_sds) - if len(s_list) > 256: - # Some hard limit on 256 chars total - raise ValueError(("Adding %r would go beyond the " - "256 maximum search list character limit") - % (search_domain)) - self._remove_option('search') - self._contents.append(('option', ['search', s_list, ''])) - return flat_sds - - @local_domain.setter - def local_domain(self, domain): - self.parse() - self._remove_option('domain') - self._contents.append(('option', ['domain', str(domain), ''])) - return domain - - def _parse(self, contents): - entries = [] - for (i, line) in enumerate(contents.splitlines()): - sline = line.strip() - if not sline: - entries.append(('blank', [line])) - continue - (head, tail) = chop_comment(line, ';#') - if not len(head.strip()): - entries.append(('all_comment', [line])) - continue - if not tail: - tail = '' - try: - (cfg_opt, cfg_values) = head.split(None, 1) - except (IndexError, ValueError): - raise IOError("Incorrectly formatted resolv.conf line %s" - % (i + 1)) - if cfg_opt not in ['nameserver', 'domain', - 'search', 'sortlist', 'options']: - raise IOError("Unexpected resolv.conf option %s" % (cfg_opt)) - entries.append(("option", [cfg_opt, cfg_values, tail])) - return entries diff --git a/cloudinit/distros/parsers/sys_conf.py b/cloudinit/distros/parsers/sys_conf.py deleted file mode 100644 index 6157cf32..00000000 --- a/cloudinit/distros/parsers/sys_conf.py +++ /dev/null @@ -1,113 +0,0 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow <harlowja@yahoo-inc.com> -# -# 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 <http://www.gnu.org/licenses/>. - -import six -from six import StringIO - -import pipes -import re - -# This library is used to parse/write -# out the various sysconfig files edited (best attempt effort) -# -# It has to be slightly modified though -# to ensure that all values are quoted/unquoted correctly -# since these configs are usually sourced into -# bash scripts... -import configobj - -# See: http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html -# or look at the 'param_expand()' function in the subst.c file in the bash -# source tarball... -SHELL_VAR_RULE = r'[a-zA-Z_]+[a-zA-Z0-9_]*' -SHELL_VAR_REGEXES = [ - # Basic variables - re.compile(r"\$" + SHELL_VAR_RULE), - # Things like $?, $0, $-, $@ - re.compile(r"\$[0-9#\?\-@\*]"), - # Things like ${blah:1} - but this one - # gets very complex so just try the - # simple path - re.compile(r"\$\{.+\}"), -] - - -def _contains_shell_variable(text): - for r in SHELL_VAR_REGEXES: - if r.search(text): - return True - return False - - -class SysConf(configobj.ConfigObj): - def __init__(self, contents): - configobj.ConfigObj.__init__(self, contents, - interpolation=False, - write_empty_values=True) - - def __str__(self): - contents = self.write() - out_contents = StringIO() - if isinstance(contents, (list, tuple)): - out_contents.write("\n".join(contents)) - else: - out_contents.write(str(contents)) - return out_contents.getvalue() - - def _quote(self, value, multiline=False): - if not isinstance(value, six.string_types): - raise ValueError('Value "%s" is not a string' % (value)) - if len(value) == 0: - return '' - quot_func = None - if value[0] in ['"', "'"] and value[-1] in ['"', "'"]: - if len(value) == 1: - quot_func = (lambda x: self._get_single_quote(x) % x) - else: - # Quote whitespace if it isn't the start + end of a shell command - if value.strip().startswith("$(") and value.strip().endswith(")"): - pass - else: - if re.search(r"[\t\r\n ]", value): - if _contains_shell_variable(value): - # If it contains shell variables then we likely want to - # leave it alone since the pipes.quote function likes - # to use single quotes which won't get expanded... - if re.search(r"[\n\"']", value): - quot_func = (lambda x: - self._get_triple_quote(x) % x) - else: - quot_func = (lambda x: - self._get_single_quote(x) % x) - else: - quot_func = pipes.quote - if not quot_func: - return value - return quot_func(value) - - def _write_line(self, indent_string, entry, this_entry, comment): - # Ensure it is formatted fine for - # how these sysconfig scripts are used - val = self._decode_element(self._quote(this_entry)) - key = self._decode_element(self._quote(entry)) - cmnt = self._decode_element(comment) - return '%s%s%s%s%s' % (indent_string, - key, - self._a_to_u('='), - val, - cmnt) |