components/ruby/puppet-solaris/files/update_smf.py
changeset 7565 48aa82a0931f
parent 7564 f958607559a6
child 7566 34f2284a605f
--- a/components/ruby/puppet-solaris/files/update_smf.py	Wed Jan 11 15:24:27 2017 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-#!/usr/bin/python2.7
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
-#
-
-'''
-Utility program for helping with the upgrade of puppet to a newer
-version.  This program will take a puppet configuration file that
-has been generated via the command sequence
-
-puppet agent --genconfig > puppet.conf
-
-and use the data in that configuration file to replace the
-associated Puppet SMF user configuratable properties with the
-properties that are allowed in the new version of puppet
-
-NOTE: This file should not be included with the puppet release
-'''
-
-import os
-import re
-import sys
-
-from lxml import etree
-from optparse import OptionParser
-
-
-COMMENT_PATTERN = re.compile(".*# ?(.*)")
-CONFIG_VALUE_PATTERN = re.compile("([\S]+)\s*=\s*(\S*)")
-
-DEFAULT_VALUE_STR = "The default value is "
-
-# SMF defined property types.  For a list of
-# all available types see
-# /usr/share/lib/xml/dtd/service_bundle.dtd.1
-TYPE_ASTRING = "astring"
-TYPE_BOOLEAN = "boolean"
-TYPE_INTEGER = "integer"
-TYPE_HOST = "host"
-TYPE_HOSTNAME = "hostname"
-TYPE_NETADDRESS = "net_address"
-TYPE_URI = "uri"
-
-
-# Dictionary of currently defined property types to associate
-# with a specified property.  Any property not defined here
-# is assumed to have a property type of astring, integer,
-# or boolean
-PROP_TYPE = {
-    'server': TYPE_HOST,
-    'archive_file_server': TYPE_HOST,
-    'bindaddress': TYPE_NETADDRESS,
-    'ca_server': TYPE_HOST,
-    'certname': TYPE_HOSTNAME,
-    'couchdb_url': TYPE_URI,
-    'dbserver': TYPE_HOST,
-    'dns_alt_names': TYPE_HOST,
-    'http_proxy_host': TYPE_HOST,
-    'inventory_server': TYPE_HOST,
-    'ldapserver': TYPE_HOST,
-    'ldapuser': TYPE_HOSTNAME,
-    'module_repository': TYPE_URI,
-    'queue_source': TYPE_URI,
-    'report_server': TYPE_HOST,
-    'reporturl': TYPE_URI,
-    'smtpserver': TYPE_HOST,
-    'srv_domain': TYPE_HOST,
-}
-
-# Dictionary used to hold properites and the resulting xml code
-PUPPET_CONFIG_DICT = dict()
-
-
-def err(msg):
-    '''Output standard error message'''
-    # Duplicate the syntax of the parser.error
-    sys.stderr.write("%(prog)s: error: %(msg)s\n" %
-                     {"prog": os.path.basename(sys.argv[0]), "msg": msg})
-
-
-def create_config_element(key, key_type, desc_text):
-    '''Create a basic xml entry following the basic pattern of
-
-        <prop_pattern name='${key}' type='${key_type}'
-                required='false'>
-                    <description> <loctext xml:lang='C'>
-                         ${desc_text}
-                    </loctext> </description>
-        </prop_pattern>
-    '''
-    prop_pattern = etree.Element(
-        "prop_pattern",
-        name=key,
-        type=key_type,
-        required="false")
-    desc = etree.SubElement(prop_pattern, "description")
-    loctext = etree.SubElement(desc, "loctext")
-    loctext.text = "\n%s\n\t    " % desc_text
-    loctext.set('{http://www.w3.org/XML/1998/namespace}lang', 'C')
-    return prop_pattern
-
-
-def determine_type(key, value):
-    '''Determine the xml property type to associate with the
-       specified key
-    '''
-
-    # Does the key have a specified xml property type
-    # already defined?
-    try:
-        return PROP_TYPE[key]
-    except KeyError:
-        pass
-
-    # Use the value to determine the xml property type
-    if value.isdigit():
-        return TYPE_INTEGER
-    if value.lower() in ['false', 'true']:
-        return TYPE_BOOLEAN
-    return TYPE_ASTRING
-
-
-def process_grouping(lines):
-    '''Process the lines in the list.  The last entry should be
-       a 'key=value' entry
-    '''
-
-    # The last field should be a key = value pair
-    # If it's not then the format of the file is not matching
-    # the expected format of
-    #
-    # Description
-    # The default value is "xxxx"
-    # key = value
-    #
-    key_value = lines.pop()
-    match = CONFIG_VALUE_PATTERN.match(key_value)
-    if not match:
-        raise TypeError("Last line in grouping is not in expected "
-                        "format of 'key = value'\n%s" %
-                        "\n".join(lines))
-    key = match.group(1)
-    value = match.group(2)
-
-    default_value_line = lines.pop()
-    if not default_value_line.startswith(DEFAULT_VALUE_STR):
-        # Not a match.  Last line was still part of the description
-        lines.append(default_value_line)
-
-    key_type = determine_type(key, value)
-
-    # remaining lines are the descriptor field
-    desc = '\n'.join(lines)
-    PUPPET_CONFIG_DICT[key] = (key, key_type, desc)
-
-
-def parse_puppet_config(filename):
-    '''Parse the puppet configuration file that is generated by
-       puppet agent --genconfig
-    '''
-    parameter_list = []
-    agent_check = True
-    with open(filename, 'r') as f_handle:
-        for line in f_handle:
-            if agent_check:
-                if line.startswith("[agent]"):
-                    # Throw away the initial starting block code in the
-                    del parameter_list[:]
-                    agent_check = False
-                    continue
-            line = line.strip().replace("\n", "")
-            if not line:
-                # If parameter_list is not empty, process the data and
-                # generate an xml structure
-                process_grouping(parameter_list)
-                # Done processing, delete all the saved entries
-                del parameter_list[:]
-                continue
-
-            match = COMMENT_PATTERN.match(line)
-            if match:
-                line = match.group(1)
-            parameter_list.append(line)
-    f_handle.close()
-
-
-def update_smf_file(smf_xml_file, output_file, version):
-    '''Replace the puppet property definitions in the specified SMF
-       file with those that are stored in PUPPET_CONFIG_DICT
-    '''
-
-    try:
-        parser = etree.XMLParser(remove_blank_text=True)
-        tree = etree.parse(smf_xml_file, parser)
-        root = tree.getroot()
-        template = root.find("service/template")
-        puppet_desc = template.find("common_name/loctext")
-        puppet_desc.text = "Puppet version %s" % version
-
-        pg_pattern = template.find("pg_pattern")
-    except IOError as msg:
-        err(msg)
-        return -1
-    except etree.XMLSyntaxError as msg:
-        err(msg)
-        return -1
-    except NameError as msg:
-        err("XML file %s does not match expected formated" % smf_xml_file)
-
-    # Delete the pg_pattern nodes and it's children
-    # This is the structure that will be rebuilt based
-    # on the genconfig information that was read in
-    if pg_pattern is not None:
-        template.remove(pg_pattern)
-
-    # <pg_pattern name='config' type='application' required='false'>
-    pg_pattern = etree.SubElement(
-        template,
-        "pg_pattern",
-        name="config",
-        type="application",
-        required="false")
-    for key in sorted(PUPPET_CONFIG_DICT.iterkeys()):
-        values = PUPPET_CONFIG_DICT[key]
-        element = create_config_element(values[0], values[1], values[2])
-        pg_pattern.append(element)
-
-    # Write out the contents of the updated puppet SMF config file
-    print "Writting out contents of new SMF configuration file to: %s" % \
-        output_file
-    with open(output_file, "w") as f_handle:
-        f_handle.write(etree.tostring(tree, pretty_print=True))
-    f_handle.close()
-
-
-def option_list():
-    '''Build the option list for this utility'''
-    desc = "Utility for assisting in the upgrading of Solaris Puppet SMF file"
-    usage = "usage: %prog -c <puppet_config_file> -s <smf_confilg_file> " \
-            "-v <puppet_version> [-o <output_file>]\n"
-    opt_list = OptionParser(description=desc, usage=usage)
-
-    opt_list.add_option("-c", "--config", dest="config", default=None,
-                        action="store", type="string", nargs=1,
-                        metavar="<puppet_config_file>",
-                        help="Puppet configuration file generated via"
-                             "genconfig option to puppet. i.e. "
-                             "puppet agent --genconfig > puppet.conf")
-    opt_list.add_option("-s", "--smf", dest="smf_xml", default=None,
-                        action="store", type="string", nargs=1,
-                        metavar="<smf_config_file>",
-                        help="Current solaris Puppet SMF XML configuration"
-                             " file. This file is located in <userland_tree>"
-                             "/components/puppet/files/puppet.xml")
-    opt_list.add_option("-o", "--output", dest="output", default=None,
-                        action="store", type="string", nargs=1,
-                        metavar="<output_file>",
-                        help="The name of the new puppet.xml file ")
-    opt_list.add_option("-v", "--version", dest="version", default="None",
-                        action="store", type="string", nargs=1,
-                        metavar="<puppet_version>",
-                        help="Puppet Version of update")
-
-    return opt_list
-
-
-def main():
-    '''Execute this utility based on the options supplied by the user'''
-    parser = option_list()
-
-    (options, _args) = parser.parse_args()
-
-    if not options.output and options.version:
-        options.output = "puppet.%s.xml" % options.version
-
-    if not options.config or not options.smf_xml or \
-            not options.output or not options.version:
-        err("Required options not specified")
-        parser.print_help()
-        sys.exit(-1)
-
-    if not os.path.isfile(options.config):
-        err("%s does not exist or is not a regular file\n"
-            % options.config)
-        sys.exit(-1)
-    if not os.path.isfile(options.smf_xml):
-        err("%s does not exist or is not a regular file\n"
-            % options.smf_xml)
-        sys.exit(-1)
-    if os.path.exists(options.output):
-        err("specified file %s already exist\n"
-            % options.output)
-        sys.exit(-1)
-
-    parse_puppet_config(options.config)
-    update_smf_file(options.smf_xml, options.output, options.version)
-
-if __name__ == '__main__':
-    main()