diff options
-rw-r--r-- | doc/help/troubleshooting.txt | 4 | ||||
-rw-r--r-- | doc/server/plugins/generators/rules.txt | 2 | ||||
-rw-r--r-- | man/bcfg2-info.8 | 4 | ||||
-rw-r--r-- | osx/Makefile | 6 | ||||
-rw-r--r-- | redhat/systemd/bcfg2-server.service | 13 | ||||
-rw-r--r-- | redhat/systemd/bcfg2.service | 13 | ||||
-rw-r--r-- | schemas/bundle.xsd | 213 | ||||
-rw-r--r-- | schemas/pkgtype.xsd | 1 | ||||
-rw-r--r-- | src/lib/Server/Admin/Compare.py | 159 | ||||
-rw-r--r-- | src/lib/Server/Admin/Viz.py | 28 | ||||
-rw-r--r-- | src/lib/Server/Plugin.py | 2 | ||||
-rw-r--r-- | src/lib/Server/Plugins/Metadata.py | 41 | ||||
-rwxr-xr-x | src/sbin/bcfg2-info | 7 | ||||
-rwxr-xr-x | tools/export2.py | 18 |
14 files changed, 296 insertions, 215 deletions
diff --git a/doc/help/troubleshooting.txt b/doc/help/troubleshooting.txt index 1cd61a8f3..cb68a02c5 100644 --- a/doc/help/troubleshooting.txt +++ b/doc/help/troubleshooting.txt @@ -200,8 +200,8 @@ Server Errors | Packages: No matching | Server | None of the sources | [s12]_ | | sources for client | | defined in the | | | <clientname>; improper group | | Package plugin's | | -| memberships? | | ``config.xml``apply | | -| | | to the client. | | +| memberships? | | ``config.xml`` | | +| | | apply to the client | | +------------------------------+----------+---------------------+--------------+ diff --git a/doc/server/plugins/generators/rules.txt b/doc/server/plugins/generators/rules.txt index a2953ad08..05baa2dbb 100644 --- a/doc/server/plugins/generators/rules.txt +++ b/doc/server/plugins/generators/rules.txt @@ -97,8 +97,6 @@ The Package Tag may have the following attributes: | verify | verify='false' - do not do package | String | | | verification | | +------------+----------------------------------------------+--------+ -| reloc | RPM relocation path. | String | -+------------+----------------------------------------------+--------+ | multiarch | Comma separated list of the architectures of | String | | | this package that should be installed. | | +------------+----------------------------------------------+--------+ diff --git a/man/bcfg2-info.8 b/man/bcfg2-info.8 index a97f60c40..fe20d5d6c 100644 --- a/man/bcfg2-info.8 +++ b/man/bcfg2-info.8 @@ -83,10 +83,6 @@ Shell out to native python interpreter. .RS Display filesystem events as they are processed. .RE -.B generators -.RS -List current versions of generators. -.RE .B groups .RS List groups diff --git a/osx/Makefile b/osx/Makefile index 075628668..8d16b42ae 100644 --- a/osx/Makefile +++ b/osx/Makefile @@ -1,6 +1,6 @@ -PYVERSION := $(shell /usr/bin/python -c "import sys; print sys.version[0:3]") -PYMAJORVERSION := $(shell /usr/bin/python -c "import sys; print sys.version[0:1]") -PYMINORVERSION := $(shell /usr/bin/python -c "import sys; print sys.version[2:3]") +PYVERSION := $(shell /usr/bin/python -c "import sys; print '%s.%s' % (sys.version_info[0], sys.version_info[1])"python -c "import sys; print sys.version[0:3]") +PYMAJORVERSION := $(shell /usr/bin/python -c "import sys; print sys.version_info[0]") +PYMINORVERSION := $(shell /usr/bin/python -c "import sys; print sys.version_info[1]") PREFLIGHT = preflight POSTFLIGHT = postflight PKGROOT = bcfg2pkg diff --git a/redhat/systemd/bcfg2-server.service b/redhat/systemd/bcfg2-server.service new file mode 100644 index 000000000..641b02ec6 --- /dev/null +++ b/redhat/systemd/bcfg2-server.service @@ -0,0 +1,13 @@ +[Unit] +Description=Bcfg2 configuration daemon +After=syslog.target network.target + +[Service] +Type=forking +StandardOutput=syslog +StandardError=syslog +EnvironmentFile=-/etc/sysconfig/bcfg2 +ExecStart=/usr/bin/bcfg2-server $OPTIONS + +[Install] +WantedBy=multi-user.target diff --git a/redhat/systemd/bcfg2.service b/redhat/systemd/bcfg2.service new file mode 100644 index 000000000..a0c3afd81 --- /dev/null +++ b/redhat/systemd/bcfg2.service @@ -0,0 +1,13 @@ +[Unit] +Description=Bcfg2 configuration client +After=syslog.target network.target + +[Service] +Type=forking +StandardOutput=syslog +StandardError=syslog +EnvironmentFile=-/etc/sysconfig/bcfg2 +ExecStart=/usr/bin/bcfg2 $OPTIONS + +[Install] +WantedBy=multi-user.target diff --git a/schemas/bundle.xsd b/schemas/bundle.xsd index c0a7e08ac..2dd77e9af 100644 --- a/schemas/bundle.xsd +++ b/schemas/bundle.xsd @@ -110,6 +110,14 @@ </xsd:documentation> </xsd:annotation> </xsd:element> + <xsd:element name='Bundle' type='BundleType'> + <xsd:annotation> + <xsd:documentation> + Nesting Bundle tags is allowed in order to support + XInclude within Bundles. + </xsd:documentation> + </xsd:annotation> + </xsd:element> <xsd:element ref="py:def"/> <xsd:element ref="py:match"/> <xsd:element ref="py:choose"/> @@ -135,7 +143,113 @@ <xsd:attributeGroup ref="py:genshiAttrs"/> </xsd:complexType> - <xsd:element name='Bundle'> + <xsd:complexType name='BundleType'> + <xsd:choice minOccurs='0' maxOccurs='unbounded'> + <xsd:element name='Package' type='StructureEntry'> + <xsd:annotation> + <xsd:documentation> + Abstract implementation of a Package entry. The full + specification will be included in Rules. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='Path' type='PathEntry'> + <xsd:annotation> + <xsd:documentation> + Abstract implementation of a Path entry. The entry will + either be handled by Cfg, TGenshi, or another + DirectoryBacked plugin; or handled by Rules, in which case + the full specification of this entry will be included in + Rules. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='Service' type='StructureEntry'> + <xsd:annotation> + <xsd:documentation> + Abstract implementation of a Service entry. The full + specification will be included in Rules. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='Action' type='StructureEntry'> + <xsd:annotation> + <xsd:documentation> + Abstract implementation of an Action entry. The full + specification will be included in Rules. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='BoundPackage' type='PackageType'> + <xsd:annotation> + <xsd:documentation> + Fully bound description of a software package to be managed. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='BoundPath' type='BoundPathEntry'> + <xsd:annotation> + <xsd:documentation> + Fully bound description of a filesystem path to be handled + by the POSIX driver. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='BoundService' type='ServiceType'> + <xsd:annotation> + <xsd:documentation> + Fully bound description of a system service to be managed. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='BoundAction' type='ActionType'> + <xsd:annotation> + <xsd:documentation> + Fully bound description of a command to be run. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='Group' type='GroupType'> + <xsd:annotation> + <xsd:documentation> + Elements within Group tags only apply to clients that are + members of that group + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='Client' type='GroupType'> + <xsd:annotation> + <xsd:documentation> + Elements within Client tags only apply to the named client + (or vice-versa; see #element_negate below) + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name='Bundle' type='BundleType'> + <xsd:annotation> + <xsd:documentation> + Nesting Bundle tags is allowed in order to support + XInclude within Bundles. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element ref="py:def"/> + <xsd:element ref="py:match"/> + <xsd:element ref="py:choose"/> + <xsd:element ref="py:for"/> + <xsd:element ref="py:if"/> + <xsd:element ref="py:with"/> + <xsd:element ref="py:replace"/> + </xsd:choice> + <xsd:attribute type='xsd:string' name='description' /> + <xsd:attribute type='xsd:string' name='name'/> + <xsd:attribute type='xsd:string' name='version'/> + <xsd:attribute type='xsd:string' name='origin'/> + <xsd:attribute type='xsd:string' name='revision'/> + <xsd:attributeGroup ref="py:genshiAttrs"/> + </xsd:complexType> + + <xsd:element name='Bundle' type='BundleType'> <xsd:annotation> <xsd:documentation> A bundle describes a group of inter-dependent configuration @@ -150,102 +264,5 @@ that a given client will receive. </xsd:documentation> </xsd:annotation> - <xsd:complexType> - <xsd:choice minOccurs='0' maxOccurs='unbounded'> - <xsd:element name='Package' type='StructureEntry'> - <xsd:annotation> - <xsd:documentation> - Abstract implementation of a Package entry. The full - specification will be included in Rules. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='Path' type='PathEntry'> - <xsd:annotation> - <xsd:documentation> - Abstract implementation of a Path entry. The entry will - either be handled by Cfg, TGenshi, or another - DirectoryBacked plugin; or handled by Rules, in which case - the full specification of this entry will be included in - Rules. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='Service' type='StructureEntry'> - <xsd:annotation> - <xsd:documentation> - Abstract implementation of a Service entry. The full - specification will be included in Rules. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='Action' type='StructureEntry'> - <xsd:annotation> - <xsd:documentation> - Abstract implementation of an Action entry. The full - specification will be included in Rules. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='BoundPackage' type='PackageType'> - <xsd:annotation> - <xsd:documentation> - Fully bound description of a software package to be managed. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='BoundPath' type='BoundPathEntry'> - <xsd:annotation> - <xsd:documentation> - Fully bound description of a filesystem path to be handled - by the POSIX driver. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='BoundService' type='ServiceType'> - <xsd:annotation> - <xsd:documentation> - Fully bound description of a system service to be managed. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='BoundAction' type='ActionType'> - <xsd:annotation> - <xsd:documentation> - Fully bound description of a command to be run. - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='Group' type='GroupType'> - <xsd:annotation> - <xsd:documentation> - Elements within Group tags only apply to clients that are - members of that group - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element name='Client' type='GroupType'> - <xsd:annotation> - <xsd:documentation> - Elements within Client tags only apply to the named client - (or vice-versa; see #element_negate below) - </xsd:documentation> - </xsd:annotation> - </xsd:element> - <xsd:element ref="py:def"/> - <xsd:element ref="py:match"/> - <xsd:element ref="py:choose"/> - <xsd:element ref="py:for"/> - <xsd:element ref="py:if"/> - <xsd:element ref="py:with"/> - <xsd:element ref="py:replace"/> - </xsd:choice> - <xsd:attribute type='xsd:string' name='description' /> - <xsd:attribute type='xsd:string' name='name'/> - <xsd:attribute type='xsd:string' name='version'/> - <xsd:attribute type='xsd:string' name='origin'/> - <xsd:attribute type='xsd:string' name='revision'/> - <xsd:attributeGroup ref="py:genshiAttrs"/> - </xsd:complexType> </xsd:element> </xsd:schema> diff --git a/schemas/pkgtype.xsd b/schemas/pkgtype.xsd index ad63cd9d2..70a466448 100644 --- a/schemas/pkgtype.xsd +++ b/schemas/pkgtype.xsd @@ -43,7 +43,6 @@ <xsd:attribute type='xsd:string' name='file'/> <xsd:attribute type='xsd:string' name='verify'/> <xsd:attribute type='xsd:string' name='simplefile'/> - <xsd:attribute type='xsd:string' name='reloc'/> <xsd:attribute type='xsd:string' name='multiarch'/> <xsd:attribute type='xsd:string' name='srcs'/> <xsd:attribute type='xsd:string' name='type'/> diff --git a/src/lib/Server/Admin/Compare.py b/src/lib/Server/Admin/Compare.py index 4c751b55a..82d0d690c 100644 --- a/src/lib/Server/Admin/Compare.py +++ b/src/lib/Server/Admin/Compare.py @@ -14,62 +14,64 @@ class Compare(Bcfg2.Server.Admin.Mode): def __init__(self, configfile): Bcfg2.Server.Admin.Mode.__init__(self, configfile) - self.important = {'Package': ['name', 'version'], - 'Service': ['name', 'status'], - 'Directory': ['name', 'owner', 'group', 'perms'], - 'SymLink': ['name', 'to'], - 'ConfigFile': ['name', 'owner', 'group', 'perms'], - 'Permissions': ['name', 'perms'], - 'PostInstall': ['name']} + self.important = {'Path': ['name', 'type', 'owner', 'group', 'perms', + 'important', 'paranoid', 'sensitive', + 'dev_type', 'major', 'minor', 'prune', + 'encoding', 'empty', 'to', 'recursive', + 'vcstype', 'sourceurl', 'revision'], + 'Package': ['name', 'type', 'version', 'simplefile', + 'verify'], + 'Service': ['name', 'type', 'status', 'mode', + 'target', 'sequence', 'parameters'], + 'Action': ['name', 'timing', 'when', 'status', + 'command'], + 'PostInstall': ['name'] + } def compareStructures(self, new, old): + if new.tag == 'Independent': + bundle = 'Base' + else: + bundle = new.get('name') + + identical = True + for child in new.getchildren(): - equiv = old.xpath('%s[@name="%s"]' % - (child.tag, child.get('name'))) - if child.tag in self.important: - print("tag type %s not handled" % (child.tag)) + if child.tag not in self.important: + print(" %s in (new) bundle %s:\n tag type not handled!" % + (child.tag, bundle)) continue + equiv = old.xpath('%s[@name="%s"]' % + (child.tag, child.get('name'))) if len(equiv) == 0: - print("didn't find matching %s %s" % - (child.tag, child.get('name'))) + print(" %s %s in bundle %s:\n only in new configuration" % + (child.tag, child.get('name'), bundle)) + identical = False continue - elif len(equiv) >= 1: - if child.tag == 'ConfigFile': - if child.text != equiv[0].text: - print(" %s %s contents differ" \ - % (child.tag, child.get('name'))) - continue - noattrmatch = [field for field in self.important[child.tag] if \ - child.get(field) != equiv[0].get(field)] - if not noattrmatch: - new.remove(child) - old.remove(equiv[0]) - else: - print(" %s %s attributes %s do not match" % \ - (child.tag, child.get('name'), noattrmatch)) - if len(old.getchildren()) == 0 and len(new.getchildren()) == 0: - return True - if new.tag == 'Independent': - name = 'Base' - else: - name = new.get('name') - both = [] - oldl = ["%s %s" % (entry.tag, entry.get('name')) for entry in old] - newl = ["%s %s" % (entry.tag, entry.get('name')) for entry in new] - for entry in newl: - if entry in oldl: - both.append(entry) - newl.remove(entry) - oldl.remove(entry) - for entry in both: - print(" %s differs (in bundle %s)" % (entry, name)) - for entry in oldl: - print(" %s only in old configuration (in bundle %s)" % (entry, - name)) - for entry in newl: - print(" %s only in new configuration (in bundle %s)" % (entry, - name)) - return False + diff = [] + if child.tag == 'Path' and child.get('type') == 'file' and \ + child.text != equiv[0].text: + diff.append('contents') + attrdiff = [field for field in self.important[child.tag] if \ + child.get(field) != equiv[0].get(field)] + if attrdiff: + diff.append('attributes (%s)' % ', '.join(attrdiff)) + if diff: + print(" %s %s in bundle %s:\n %s differ" % (child.tag, \ + child.get('name'), bundle, ' and '.join(diff))) + identical = False + + for child in old.getchildren(): + if child.tag not in self.important: + print(" %s in (old) bundle %s:\n tag type not handled!" % + (child.tag, bundle)) + elif len(new.xpath('%s[@name="%s"]' % + (child.tag, child.get('name')))) == 0: + print(" %s %s in bundle %s:\n only in old configuration" % + (child.tag, child.get('name'), bundle)) + identical = False + + return identical def compareSpecifications(self, path1, path2): try: @@ -89,30 +91,30 @@ class Compare(Bcfg2.Server.Admin.Mode): if bundle.get('name')[-4:] == '.xml': bundle.set('name', bundle.get('name')[:-4]) - rcs = [] + identical = True + + for bundle in old.findall('./Bundle'): + if len(new.xpath('Bundle[@name="%s"]' % (bundle.get('name')))) == 0: + print(" Bundle %s only in old configuration" % + bundle.get('name')) + identical = False for bundle in new.findall('./Bundle'): equiv = old.xpath('Bundle[@name="%s"]' % (bundle.get('name'))) if len(equiv) == 0: - print("couldnt find matching bundle for %s" % bundle.get('name')) - continue - if len(equiv) == 1: - if self.compareStructures(bundle, equiv[0]): - new.remove(bundle) - old.remove(equiv[0]) - rcs.append(True) - else: - rcs.append(False) - else: - print("Unmatched bundle %s" % (bundle.get('name'))) - rcs.append(False) - i1 = new.find('./Independent') - i2 = old.find('./Independent') - if self.compareStructures(i1, i2): - new.remove(i1) - old.remove(i2) - else: - rcs.append(False) - return False not in rcs + print(" Bundle %s only in new configuration" % + bundle.get('name')) + identical = False + elif not self.compareStructures(bundle, equiv[0]): + identical = False + + i1 = lxml.etree.Element('Independent') + i2 = lxml.etree.Element('Independent') + i1.extend(new.findall('./Independent/*')) + i2.extend(old.findall('./Independent/*')) + if not self.compareStructures(i1, i2): + identical = False + + return identical def __call__(self, args): Bcfg2.Server.Admin.Mode.__call__(self, args) @@ -124,19 +126,26 @@ class Compare(Bcfg2.Server.Admin.Mode): args.remove('-r') (oldd, newd) = args (old, new) = [os.listdir(spot) for spot in args] + old_extra = [] for item in old: - print("Entry:", item) + if item not in new: + old_extra.append(item) + continue + print("File: %s" % item) state = self.__call__([oldd + '/' + item, newd + '/' + item]) new.remove(item) if state: - print("Entry:", item, "good") + print("File %s is good" % item) else: - print("Entry:", item, "bad") + print("File %s is bad" % item) if new: - print("new has extra entries", new) + print("%s has extra files: %s" % (newd, ', '.join(new))) + if old_extra: + print("%s has extra files: %s" % (oldd, ', '.join(old_extra))) return try: (old, new) = args + return self.compareSpecifications(new, old) except IndexError: print(self.__call__.__doc__) raise SystemExit(1) diff --git a/src/lib/Server/Admin/Viz.py b/src/lib/Server/Admin/Viz.py index f39e6d7a8..bd7c6dd05 100644 --- a/src/lib/Server/Admin/Viz.py +++ b/src/lib/Server/Admin/Viz.py @@ -1,5 +1,6 @@ import getopt from subprocess import Popen, PIPE +import sys import Bcfg2.Server.Admin @@ -8,18 +9,22 @@ class Viz(Bcfg2.Server.Admin.MetadataCore): __shorthelp__ = "Produce graphviz diagrams of metadata structures" __longhelp__ = (__shorthelp__ + "\n\nbcfg2-admin viz [--includehosts] " "[--includebundles] [--includekey] " + "[--only-client clientname] " "[-o output.png] [--raw]\n") __usage__ = ("bcfg2-admin viz [options]\n\n" - " %-25s%s\n" - " %-25s%s\n" - " %-25s%s\n" - " %-25s%s\n" % + " %-32s%s\n" + " %-32s%s\n" + " %-32s%s\n" + " %-32s%s\n" + " %-32s%s\n" % ("-H, --includehosts", "include hosts in the viz output", "-b, --includebundles", "include bundles in the viz output", "-k, --includekey", "show a key for different digraph shapes", + "-c, --only-client <clientname>", + "show only the groups, bundles for the named client", "-o, --outfile <file>", "write viz output to an output file")) @@ -42,18 +47,21 @@ class Viz(Bcfg2.Server.Admin.MetadataCore): Bcfg2.Server.Admin.MetadataCore.__call__(self, args) # First get options to the 'viz' subcommand try: - opts, args = getopt.getopt(args, 'Hbko:', + opts, args = getopt.getopt(args, 'Hbkc:o:', ['includehosts', 'includebundles', - 'includekey', 'outfile=']) + 'includekey', 'only-client=', 'outfile=']) except getopt.GetoptError: msg = sys.exc_info()[1] print(msg) + print(self.__longhelp__) + raise SystemExit(1) #FIXME: is this for --raw? #rset = False hset = False bset = False kset = False + only_client = None outputfile = False for opt, arg in opts: if opt in ("-H", "--includehosts"): @@ -62,16 +70,18 @@ class Viz(Bcfg2.Server.Admin.MetadataCore): bset = True elif opt in ("-k", "--includekey"): kset = True + elif opt in ("-c", "--only-client"): + only_client = arg elif opt in ("-o", "--outfile"): outputfile = arg data = self.Visualize(self.get_repo_path(), hset, bset, - kset, outputfile) + kset, only_client, outputfile) print(data) raise SystemExit(0) def Visualize(self, repopath, hosts=False, - bundles=False, key=False, output=False): + bundles=False, key=False, only_client=None, output=False): """Build visualization of groups file.""" if output: format = output.split('.')[-1] @@ -90,7 +100,7 @@ class Viz(Bcfg2.Server.Admin.MetadataCore): raise SystemExit(1) dotpipe.stdin.write('\trankdir="LR";\n') dotpipe.stdin.write(self.metadata.viz(hosts, bundles, - key, self.colors)) + key, only_client, self.colors)) if key: dotpipe.stdin.write("\tsubgraph cluster_key {\n") dotpipe.stdin.write('''\tstyle="filled";\n''') diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 3841e637d..a05c537e5 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -927,7 +927,7 @@ class GroupSpool(Plugin, Generator): if not posixpath.isdir(epath): # do not pass through directory events self.entries[ident].handle_event(event) - if action == 'changed': + if action == 'changed' and ident in self.entries: self.entries[ident].handle_event(event) elif action == 'deleted': fbase = self.handles[event.requestID] + event.filename diff --git a/src/lib/Server/Plugins/Metadata.py b/src/lib/Server/Plugins/Metadata.py index 6570f2912..7fc34f178 100644 --- a/src/lib/Server/Plugins/Metadata.py +++ b/src/lib/Server/Plugins/Metadata.py @@ -782,8 +782,20 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, xdict['xquery'][0].set('auth', 'cert') self.clients_xml.write_xml(xdict['filename'], xdict['xmltree']) - def viz(self, hosts, bundles, key, colors): + def viz(self, hosts, bundles, key, only_client, colors): """Admin mode viz support.""" + if only_client: + clientmeta = self.core.build_metadata(only_client) + + def include_client(client): + return not only_client or client != only_client + + def include_bundle(bundle): + return not only_client or bundle in clientmeta.bundles + + def include_group(group): + return not only_client or group in clientmeta.groups + groups_tree = lxml.etree.parse(self.data + "/groups.xml") try: groups_tree.xinclude() @@ -791,7 +803,6 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, self.logger.error("Failed to process XInclude for file %s" % dest) groups = groups_tree.getroot() categories = {'default': 'grey83'} - instances = {} viz_str = "" egroups = groups.findall("Group") + groups.findall('.//Groups/Group') for group in egroups: @@ -801,8 +812,11 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, if None in categories: del categories[None] if hosts: + instances = {} clients = self.clients for client, profile in list(clients.items()): + if include_client(client): + continue if profile in instances: instances[profile].append(client) else: @@ -817,7 +831,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, bundles = [] [bundles.append(bund.get('name')) \ for bund in groups.findall('.//Bundle') \ - if bund.get('name') not in bundles] + if bund.get('name') not in bundles \ + and include_bundle(bund.get('name'))] bundles.sort() for bundle in bundles: viz_str += '''\t"bundle-%s" [ label="%s", shape="septagon"];\n''' \ @@ -829,20 +844,22 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, else: style = "filled" gseen.append(group.get('name')) - viz_str += '\t"group-%s" [label="%s", style="%s", fillcolor=%s];\n' % \ - (group.get('name'), group.get('name'), style, group.get('color')) - if bundles: - for bundle in group.findall('Bundle'): - viz_str += '\t"group-%s" -> "bundle-%s";\n' % \ - (group.get('name'), bundle.get('name')) + if include_group(group.get('name')): + viz_str += '\t"group-%s" [label="%s", style="%s", fillcolor=%s];\n' % \ + (group.get('name'), group.get('name'), style, group.get('color')) + if bundles: + for bundle in group.findall('Bundle'): + viz_str += '\t"group-%s" -> "bundle-%s";\n' % \ + (group.get('name'), bundle.get('name')) gfmt = '\t"group-%s" [label="%s", style="filled", fillcolor="grey83"];\n' for group in egroups: for parent in group.findall('Group'): - if parent.get('name') not in gseen: + if parent.get('name') not in gseen and include_group(parent.get('name')): viz_str += gfmt % (parent.get('name'), parent.get('name')) gseen.append(parent.get("name")) - viz_str += '\t"group-%s" -> "group-%s" ;\n' % \ - (group.get('name'), parent.get('name')) + if include_group(group.get('name')): + viz_str += '\t"group-%s" -> "group-%s" ;\n' % \ + (group.get('name'), parent.get('name')) if key: for category in categories: viz_str += '''\t"''' + category + '''" [label="''' + category + \ diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index 07953ae69..951a5df58 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -37,7 +37,6 @@ clients - Print out client/profile information config - Print out the configuration of the Bcfg2 server debug - Shell out to native python interpreter event_debug - Display filesystem events as they are processed -generators - List current versions of generators groups - List groups help - Print this list of available commands mappings <type*> <name*> - Print generator mappings for optional type and name @@ -311,12 +310,6 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): ] printTabular(output) - - def do_generators(self, _): - """Print out generator info.""" - for generator in self.generators: - print(generator.__version__) - def do_showentries(self, args): """Show abstract configuration entries for a given host.""" arglen = len(args.split()) diff --git a/tools/export2.py b/tools/export2.py index 0b8cc159d..567d4b227 100755 --- a/tools/export2.py +++ b/tools/export2.py @@ -72,10 +72,17 @@ def main(argv=None): help = 'run in debun mode', default = False, dest = 'debug') + p.add_option('--paranoid', '-P', + action = 'store_true', + help = 'run in paranoid mode, make changes but do not commit to repository', + default = False, + dest = 'paranoid') options, arguments = p.parse_args() if options.debug: print options + print "What should debug mode do?" + quit() # py3k compatibility try: @@ -180,6 +187,8 @@ def main(argv=None): #FIXME: do this using python-dulwich commando = {} + commando["vcs_diff"] = "git diff" + commando["vcs_commit"] = "git commit -asm 'Version bump to %s'" % version # NOTE: This will use the default email address key. If you want to sign the tag @@ -196,13 +205,20 @@ def main(argv=None): commando["scp_archive"] = "scp %s* terra.mcs.anl.gov:/mcs/ftp/pub/bcfg/" % tarname # Execute the commands - commando_orders = ["vcs_commit","vcs_tag","create_archive","gpg_encrypt","scp_archive"] + if options.paranoid: + commando_orders = ["vcs_diff"] + else: + commando_orders = ["vcs_commit","vcs_tag","create_archive","gpg_encrypt","scp_archive"] + if options.dryrun: for cmd in commando_orders: print "*** dry-run: %s" % commando[cmd] else: for cmd in commando_orders: output = run(commando[cmd])[0].strip() + if options.verbose: + print output + print "Ran '%s' with above output." % cmd if __name__ == '__main__': sys.exit(main()) |