diff options
-rw-r--r-- | BUGS | 21 | ||||
-rw-r--r-- | COPYING | 19 | ||||
-rw-r--r-- | Changelog | 204 | ||||
-rw-r--r-- | FAQ | 53 | ||||
-rw-r--r-- | INTERNALS | 194 | ||||
-rw-r--r-- | README | 63 | ||||
-rw-r--r-- | etc/pm-config | 126 | ||||
-rwxr-xr-x | install | 4 | ||||
-rw-r--r-- | stuff | 120 | ||||
-rw-r--r-- | todo | 2 | ||||
-rwxr-xr-x | usr/sbin/pm-autocast | 440 | ||||
-rwxr-xr-x | usr/sbin/pm-build-md5image | 27 | ||||
-rwxr-xr-x | usr/sbin/pm-exclude | 31 | ||||
-rwxr-xr-x | usr/sbin/pm-grab | 42 | ||||
-rwxr-xr-x | usr/sbin/pm-image-diff | 52 | ||||
-rwxr-xr-x | usr/sbin/pm-post-cast | 270 | ||||
-rwxr-xr-x | usr/sbin/pm-pre-cast | 54 | ||||
-rwxr-xr-x | usr/sbin/pm-report-all | 104 | ||||
-rwxr-xr-x | usr/sbin/pm-restore | 169 | ||||
-rwxr-xr-x | usr/sbin/pm-seer | 667 | ||||
-rwxr-xr-x | usr/sbin/pm-setup | 74 | ||||
-rwxr-xr-x | usr/sbin/pm-test | 227 | ||||
-rwxr-xr-x | usr/sbin/pm-test-cast | 94 | ||||
-rwxr-xr-x | usr/sbin/pm-update | 97 | ||||
-rw-r--r-- | usr/share/fprotect.lst | 1 |
25 files changed, 3155 insertions, 0 deletions
@@ -0,0 +1,21 @@ +just so we are clear here is a list of bugs i already know about: + +prometheus can not handle sorcery bugs well, this means that if sorcery +hangs for whatever reason, which it does, if you run it for days on end +like have been, prometheus is helpless to stop it. + +If bugzilla goes down addbug breaks miserably and gives up, someday I +will make prometheus handle this more gracefully + +pm-update doesnt do cvs, but seeing as how we still mostly use p4... +i think thats okay for now. + +if you ctrl-c out of prometheus somewhere the lock file sticks around +and prometheus sees it later when you reload it. For some reason i +have been unsuccessful at making it check for the existance of another +pm-test process. + +Some would say this md5sum image stuff is a bug because it takes so +long. However in other files I have clearly stated my opinion on this. +Besides it works really well. + @@ -0,0 +1,19 @@ +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..c6dce4a --- /dev/null +++ b/Changelog @@ -0,0 +1,204 @@ +2006-04-19 Seth Alan Woolley + * pm-build-md5image: Really fix PRUNES to be properly regex. + * pm-config: Correct the regular expression to protect pm-config. + +2006-04-17 Seth Alan Woolley + * pm-autocast: Fix expect strings to be properly unanchored. + * pm-config: Fix PRUNEs to be properly regular expressions. + +2005-05-30 Paul Mahon + * pm-autocast: Updated some of the strings for the new sorcery + +0.3.3 + +updated/rewrote pm-autocast to be more robust +added sectioning support, now one can say +pm-test ham Ham +(ham being a section, and Ham being the bugzilla component) + +lists are now more configurable and are lists that may someday be sharable are +moved to a shared directory under $PMDIR/lists + +various bits and pieces of code cleanup/documentation have appeared + +0.3.1-pre4-6 + +fixed annoying bugs that cropped up in quick untested changes + +0.3.1-pre2-3 + +forgot some stuff, minor changes getting it otd + +0.3.1-pre1 + +added support for requires and optional_requires. Prometheus will look +at the list of spells sorcery gave it, then after removing spells that +it thinks there are problems with, picks one at random. If none of the +spells please prometheus, it will go with the default. Note in the case +of optional_requires [none] will be choosen if no other spells work +because there is no [none] spell to upset prometheus. + +There is also support for the md5sum menu's. Prometheus notices and +records what the problem is (missing, ignored or different). Then it does +whatever the default action is, which is settable through sorcery. It +notices if the default choice was fatal and records that as well. The +reports will then also show any md5 problems in a fairly simplistic way. + +finally, in response to a bug, the PRUNE variables in the md5sum image +building code are now open for adjustment through the PRUNE_LOCAL +variable. + +0.3.0 + +hamish added some quick/dirty code make prometheus work with requires + +0.2.7 +typo in pm-restore...grrr + +0.2.6 + +added some more question responses to pm-autocast, and made the timeout +feature actually work, 30 minutes of zero input will case pm-deadlock +to be run in an attempt to break the ice, this is close to what a real +person would do. + +triggers are now essentially denied in all cases, im tired of dealing +with them atm. If it turns out to be essential I'll spend some time +trying to make them work. + +swapped the ordering of stuff in pm-seer, maybe things will be more readable + +cast.log is now bzip2'd in the snapshots as they were getting excessively +large at 9mb for most xfree86 casts... + +the now compressed cast.log is being attached to bugs using my snazzy +bugattach script now found in the bugcli spell. + +pm-restore now filters out new/different/deleted files from +/var/lib/sorcery/{protected,excluded} as well as from yet another +list known as fprotect.lst. fprotect.lst currently will be a manually +maintained list of 'notable exceptions' such as /etc/X11/xdm/Xsession. The +idea is to reduce the number of bugs about random files being left +behind. Someday in the future I may add code to add and remove things +from the list after a grace-period if its needed. + +The code added to pm-restore was mostly bored from sorcery's filter function +but modified to work for our purposes. + +Note: the filtering occurs _after_ pm-restore restores things, but +before the reporting is done, so that the system still stays the same, +but things we dont care about arent reported as bugs. + +0.2.5 +changed the way the problems.lst checks for spell updates +the old method kept the version number and updated field of the broken +spell, then looked for changes, once a change occured the spell was +taken off the list. + +It occured to me that the UPDATED field is designed for specifying +when an update _must_ occur, regardless of a version change, well at least +that is what used to be the case, and rather than redefine it according to my +goals, and force guru's to change the field whenever they update the spell, +I've decided to use md5sums instead. + +prometheus now executes +md5=$(tar c $SPELL_DIRECTORY|md5sum|cut -f1 -d' ') + +as a new way of detecting spell updates + +this is more robust in that even if a developer forgets to change the updated +field, any changes in the spell will be detected (and assumed a fix for whatever +our problem is) + +the only drawback is that fixes not related to a bug we found in the +spell will cause the spell to be removed from the problems list, and be +availible for casting again, leading to duplicate bugs. However given +that spells are rarely updated except for version bumps and bug-fixes, +and that prometheus bugs seem to be pretty high priority, this shouldn't +be a problem. + +0.2.4 +pm-setup now adds sorcery's sustained list to the ignore lists + +fixed a bug in pm-autocast where cast seems to send an eof after the +Do you want to cast these spells? [y] +query, even though the user answers 'y' +I had to instruct expect to wait for an eof...hopefully things wont +break because of this + +pm-restore now uses the --notriggers option when calling dispel, this +is to avoid the annoying problems shown in bug 4111 + +pm-restore also now does snapshot restoration in a safer way +instead of deleting new files first, it deletes them last, leaving room +for restoring deleted files and changed files. This caused an obscure bug +whereby cut (and other things) had been moved from /usr/bin to /bin and +prometheus was deleting the /bin version before it restored the /usr/bin/ +version, essentially causing it to stop functioning. (sorry demon_lord) + +fixed a bug in pm-seer whereby spells with identical versions were +masking each other off the summary. + +0.2.3 +apparently perl doesnt like this following: +$foo="stuff++"; +m/^$foo/; +it complains because it sees the ++ as a nested operator, and cant handle it. +I found out that m/^\Q$foo/; solves our problem, so this does it. +See bug 4057 for reference. + +fixed some other annoyances with pm-seer + + +0.2.2 + +fixed a bug in pm-update that made it impossible for prometheus to remove +spells from the updated list. + +fixed some stuff in pm-seer, but nothing major + + +0.2.1 +various bug fixes: +made pm-report-all ask for a report of smaller size which was provoking +bugs in pm-seer's trimming code + +tried to fix pm-seer's trimming code + +changed pm-post-cast to grep for 'failure' and 'failed instead of just +'failure', sometime spells dont cast due to missing source and cast +reports 'failed' which obviously doesnt match 'failure' + +made pm-seer's high level summary try to make a better guess at the +number of things its talking about on each line. +"At least 'n' cast(s) failed" + +0.2 +excluded.lst IS NO MORE you need to re-run pm-setup if you were running 0.1 +sorry + +there is a more complex exclusion system that now handles most implicit +casts/dispels well. + +pm-autocast uses expect, which answers questions from cast in a sensable +manner it can also choose defaults or answer some questions randomly. + +pm-deadlock was added as a helper to pm-autocast + +problems.lst was added, it stored a record of all borked spells and +during pm-uopdates things are taken off if they are new. + +pm-update will sync off of p4 + +pm-seer was revamped and says more stuff. + +pm-config was prettied to do better with defaults being overridden + +pm-report-all now has options to email you successes as well as failures + +files that end up in /usr/local after cast are noticed and dealt with +appropriatly + +'various bug fixes' + +I think thats it... @@ -0,0 +1,53 @@ +What is it? +prometheus is an automated testing suite for sourcemage + +Why is it? +prometheus was written because we lack the man-power to test our +grimoires, but we still have plenty of spare compute cycles. + +How does it work? +you should read the INTERNALS file, but the quick overview is that it +casts things, then dispels them and reports any problems it found. + +How do i run it: +well you should look at the README file for that. But basically +get into the environment you want to run it in (UML, chroot, etc.), then +cast prometheus, then type 'pm-setup' then 'pm-test once' to get going. + +Its frozen at the end/begining of a cast! +yes...this is a probem with sorcery and should be fixed soon by our +wonderful hardworking sorcery team. In the meantime just do a 'pkill +casting'. pm-test-cast will finish up and things will keep going. +Eventually I will write an expect script to take care of this (and other +problems/features). If you know expect I want to talk to you! + +Whats the deal with this reporting stuff? +well its pointless to cast and dispel stuff if we dont get the information +about it right? Well at the moment prometheus is getting support to +email reports and/or submit them to bugzilla (cool huh?). + +I updated my system and prometheus got angry and reverted it. +Yea...prometheus is _very_ good at this, you need to re-run pm-setup +after you update stuff. Although thankfully there still should be cached +copies of everything floating around, so you can hopefully resurrect things. + +The power went out on my prometheus box +okay well you dont want to run pm-test right away because it things might +have been left in a funny state. Look at the $PMDIR/state file to try and +figure out where things were left off. Run the remaining commands. The +entire list of things is +pm-update +pm-pre-cast +pm-test-cast +pm-post-cast +pm-restore + +Most of them leave a record in the state file and get annoyed with you +if its something they didnt expect. If it says for example pm-test-cast:start +just run pm-test-cast and two subsequent scripts. After that you are +free to keep runing pm-test. Eventually support for this will be added +to pm-test, and you wont even have to think about it. + +My question isnt in here! +email me with it! I will promptly put it in here (and answer it even, +what a deal!). diff --git a/INTERNALS b/INTERNALS new file mode 100644 index 0000000..10b261e --- /dev/null +++ b/INTERNALS @@ -0,0 +1,194 @@ +If you are reading this you probably want to know how prometheus works. + +Well you are in the right place, lets get going. + +Overview: +Its best to think of prometheus in a layered sense. + +There are three 'layers', there are two top level scripts, pm-test and +pm-report-all. These are the primary interface you (the user) will +use. Next there is a middle level, these consist of scripts that do the +actual work, and are run by the top level scripts. They are: pm-update, +pm-pre-cast, pm-test-cast, pm-post-cast, pm-restore, pm-autocast and +pm-seer. At the bottom level are pm-image-diff, pm-grab, pm-build-md5image +and pm-exclude. Most of these bottom level scripts are written in perl +and do list crunching that I wouldnt want to even try in bash. + +The languages of choice are bash, perl, and expect. The bottom level +scripts are written in perl and everything above it is written in bash. If +you feel any script is better suited to be written in another language, +go for it, that is partly why i designed prometheus to be modular. + +There are also two other pieces to the puzzle: pm-setup, which essentially +sets up prometheus (so pm-test can run), and pm-config which specifies +all the configurable bits of prometheus. + +Top level: + +Prometheus is built around what i call the 'cast-dispel cycle'. +In a nutshell: +0. update (optional) +1. choose what to cast +2. cast +3. dispel +4. repeat + +This is the core design, and is the most reasonable and flexable way I +could come up with. In between 2 and 3 prometheus notices what succeeded +and what failed, and records it in what I call a snapshot (more on this +later). After step 3 prometheus restores the system to the state it was +in before step 1, with a few slight caveats. Then prometheus is ready +to begin anew at step 0 or 1. + +pm-test implements this cast dispel cycle using the various tools from +the middle level. It records a time that a cycle began at and the +subsequent scripts use that as a reference point, and the snapshot is +named after that time, which is kept in $PMDIR/currtime + +pm-report-all can be run by pm-test, or not, it depends on values from +the config file. When it does it makes a 'report' from each of the +'snapshots' then possibly sends off the report as an email or as a bug +to bugzilla. + +Middle level: +This is where the magic happens, hopefully you understand the cast-dispel +cycle, here I will flesh out the details, by listing each of the scripts +in the order it is run by pm-test. + +pm-update: +this script does a sorcery update and a scribe update. It then notices if +there are any new spells and adds them to the queue of uncast spells. The +DO_UPDATE variable in pm-config specifies whether or not it runs, its +value should be either 'yes' or 'no'. + +pm-pre-cast: +this script clears out any old activity log, and broken source trees +in /usr/src. The scripts that figure out what installed and did not +install rely on the activity logs. To simplify this code the activity +log is truncated before each run. If there is an old one, it gets saved +into activity.old, however in a running system the activity log should +actually not exist at this point; except if you happened to have done +some work in between a cast-dispel cycle *WHICH IS NOT SUPPORTED BTW* +(unless you run pm-setup first). + +pm-test-cast: +this is the crux of the whole operation. This script chooses what to cast, +and guess what? casts it. Thats it. + +pm-post-cast: +this is one of the most difficult and complicated scripts, I dont like +it. What it is reponsible for doing is parsing the activity log and +figuring out what cast and what failed. It also uses +/var/state/sorcery/packages for things that are installed. Then for every +successful cast it copies over the compile log, list of installed files, +and cached installed files. For failed casts it saves the broken source +tree into the snapshot along with the compile log and config.log for +easy access. + +pm-restore: +this is the second most complicated script IMO, next to pm-post-cast. This +script dispels everything in the success list left by pm-post-cast. Then +it notices all the things that have changed on the system. Anything that +was deleted or changed it restores, and anything that is new it +deletes. All three of these categories are included in the snapshot, +every related file is saved. + +pm-make-report: +this script is eventually going to be re-written by Duane, for now it +just makes a report listing the things attempted to be cast, the things +that worked, the things that didnt and the first thing that broke in +the activity log. + +Bottom level: + +pm-exclude: +this simple perl script does what no unix utility I could find does. It computes the set difference between two files where each line is a member. Basically if you have the lists: +a +b +c +d + +and: + +a +c + +Then running pm-exclude between the two will output b d, or the members +in the first list not in the second list. I wanted to use comm for this, +but it didnt seem to do it the way i wanted, i wanted to use diff, but +would take longer to parse its output than to run a script that does +it itself. If you know of a way to do this that is just as fast by all means +GO FOR IT! + +pm-grab: +this simple script takes an input list and gives you n random things +from it where n is a command line option. Its sole user is pm-test-cast. + +pm-build-md5image: +this script does a find across (almost) the entire file tree and computes +the md5sum of every file it finds, and dumps it to stdout. It is usually +redirected to a file. It is basically a ripoff from updatedb from the +slocate package. It ignores files from prometheus, and sorcery and other +things as best it can, you can look at the source if you really want to +see what it ignores. + +pm-image-diff: +This takes two images, from pm-build-md5image and dumps into the files +new.lst different.lst and deleted.lst what files are new, different, +or deleted. Between the first (old) and second (new) images. The md5sums +are used to compare files (clever i know). + +*NOTE* +it has been suggested to use the undocumented feature of installwatch, +which backs up all files that are changed to another directory instead +of doing thigns this way. I have considered this and while I realize +that it is faster, I do not feel that it fulfills the needs and goals +of prometheus for the following reasons: + +* prometheus is supposed to be rock solid. Using an undocumented feature + is hardly the model of stability. +* sorcery already uses installwatch and may take advantage of this new + undocumented feature in the future, and therefore I would not think that + using it myself in anyway would be improve the stability of either, + rather it could lead to unusual and confusing problems that im not + willing to deal with. +* the existing system works. Not only does it work, it works really well, + I find myself changing minor things on the system and then noticing that + prometheus found it and reverted it, everytime. That means that whatever + the original image is, prometheus will keep the system looking that way, + and this I regard as a good thing. (think reproducable) + +Snapshots: + +So what are these mythical snapshot things? Well they live in +$PMDIR/snapshot/<time> +all the sorcery /etc/sorcery/local settings are saved there +the packages and depends file from /var/state/sorcery is saved there +the current prometheus queues and lists are saved there. +the activity log is there +the success and failure subdirectory hold all the data pm-post-cast can +dig up on each spell. +the directories new, diff.new, diff.old, and deleted hold files that +pm-image-diff notices, the lists pm-image-diff makes are also kept in +the snapshot. + +Anything else i missed? + +pm-setup: +this makes the directory $PMDIR and some of the necessary things under it, +and also makes the initial md5sum_image file. It also takes that list +and cpio's all the files over to $PMDIR/image. This is the 'image' +to which prometheus will revert to after each cast-dispel cycle. + +lists: +there are a number of lists that prometheus uses. the most +important one for you is excluded.lst, it is by default everything +in /var/state/sorcery/packages, but may include other stuff for some +reason, if you remove things prometheus will think that got installed +and dispel it, you have been warned. currcast.lst is everything +that prometheus is currently casting already cast on the last +cycle. success.lst and failure.lst are those things that succeeded or +failed since the last run of pm-post-cast. known.lst is every spell that +prometheus (pm-update) could find in the grimoire EXCEPT for those in +the excluded.lst. uncast.lst is the current queue of things to cast. It +gets slowly trickled down to nothing then refilled again. @@ -0,0 +1,63 @@ +Thank you for reading the prometheus README file. + +You probably want to know how to set yourself up. +So I'll cut to the chase: +vi /etc/prometheus/pm-config ; pm-setup && pm-test forever + +You may run prometheus whereever you feel like it, a chroot, in UML, or on +a native system. The scripts assume the look and feel of a real system. So +before you run them, chroot or do whatever you need to in order to get +into the environment you need to be in. In other words, my scripts have +no idea what a chroot is, nor do they care. If you want to use a chrooted +environment chroot there first and then run the scripts (no kidding). + +There are two main scripts at the moment that are important: +pm-setup +and +pm-test + +Get into your environment, whatever that means, and run pm-setup. This +will image the system and put things in place. Try to make sure the system +is in the state you want it to be in before you run pm-setup, repeatedly +running it shouldnt hurt anything, i recommend clearing out the +PMDIR/lists directory before you try this, or at least running pm-update +again if the DO_UPDATES variable is set to 'no'. That way you wont end +up with excluded spells on the casting list... + + +After that finishes you should edit /etc/prometheus/pm-config +this is where you get to override anything in /etc/pm-config +IF YOU WANT TO SEND REPORTS TO BUGZILLA YOU MUST PUT YOUR LOGIN AND +PASSWORD HERE. There is no default prometheus account, you have to have +your own, this is so we can track bugs down to a user if we need to. + + +Once the configuration is set how you want it you are ready to go. + +pm-test harnesses all the other scripts and makes this whole things +work. You can give it the argument 'once', 'forever', or 'until'. These +are all pretty self explainitory. Once will run through the cycle +once. forever will run forever, and until takes a time after it, which +must be parsable by the date program. prometheus will not start another +cycle after that time. You can also stop the forever or until modes by +touching the file $PMDIR/stop, that will stop prometheus after the +current cycle finishes. Ctrl-C'ing out of prometheus is normally not a +good idea and can cause the next bug report to have extra information +in it from the previous pm-test run. + +Now you are probably thinking that you want to use the tinderbox +overnight, well the easy solution is to run pm-test forever as a cron job, +then at some later time touch the stop file. Or + + pm-test until 6:00 am tomorrow + +Reporting can be run at runtime after each cycle by turning on the +RUNTIME_REPORT variable (set it to 'yes'). Or you can run pm-report-all +at some other time. + +Right now pm-seer (written by Duane Malcom) is being developed. There +is also the old crappy pm-make-report script that I wrote in 30 seconds +as a proof of concept. + +I think thats just about it. +email me with questions or read the FAQ diff --git a/etc/pm-config b/etc/pm-config new file mode 100644 index 0000000..d5d3356 --- /dev/null +++ b/etc/pm-config @@ -0,0 +1,126 @@ +#for the sake of simplicity +#please override these defaults in /etc/prometheus/pm-config +#thank you + +if [ -e /etc/prometheus/pm-config ];then + source /etc/prometheus/pm-config +fi + PMDIR=${PMDIR:=/prometheus} + + SNAP_DIR=${SNAP_DIR:=${PMDIR}/snapshot} + + #the location of all local lists + LIST_DIR=${LIST_DIR:=${PMDIR}/lists} + #the location of all shared lists (ie over nfs) + #problems, known and ignore may live safely here + #when locking is in place, this is a pre-emptive re-arrange + SHARE_DIR=${SHARE_DIR:=${LIST_DIR}/share} + + #all lists of uncasts things (grimoires, sections, etc) + #live here, this directory by default is under the shared directory + #so that it too may be shared + UNCAST_DIR=${UNCAST_DIR:=${SHARE_DIR}/uncast/} + + #if one really wants this can be shared... + FPROTECT=${FPROTECT:=${LIST_DIR}/fprotect.lst} + + #this also can be shared if you really want (ie in a ubiquitous cluster) + WINNER=${WINNER:=${LIST_DIR}/winner.lst} + LOSER=${LOSER:=${LIST_DIR}/loser.lst} + + #change these if you want to not share individual ones, etc. + + #default uncast list + UNCAST=${UNCAST:=${UNCAST_DIR}/grimoire} + + #other random stuff that is sharing safe (someday) + KNOWN=${KNOWN:=${SHARE_DIR}/known.lst} + PROBLEMS=${PROBLEMS:=${SHARE_DIR}/problems.lst} + IGNORE=${IGNORE:=${SHARE_DIR}/ignore.lst} + + + GRIMOIRE=${GRIMOIRE:=test} + GRIMOIRE_PATH=/var/lib/sorcery/codex/${GRIMOIRE} + CODEX_CACHE=${CODEX_CACHE:=codex.index} + +#how long to keep stale snapshots for + KEEP_SNAP=${KEEP_SNAP:='2 weeks'} + +#how many to cast each cycle, normally 1 + NUM_CAST=${NUM_CAST:=1} + + DO_UPDATES=${DO_UPDATES:=no} + +#force an update no matter what just happened (cast exited early because +#pm-autocast decided it didnt like the depends list for whatever was chosen +#normally its good to say no here because otherwise you'll spend all day +#updating otherwise. But if you really really want to, its here. +#this has no meaning if DO_UPDATES is set to no + FORCE_UPDATES=${FORCE_UPDATES:=no} + +#clean out everything in /var/spool/sorcery +#after a cast/dispel cycle. Useful for machines with low +#hard drive space + CLEAR_SPOOL=${CLEAR_SPOOL:=no} + +#please make sure whatever variables you need to set for p4 are set in +#/etc/prometheus/pm-config + P4_SYNC=${P4_SYNC:=no} + +#turn this to no if you want prometheus to answer questions about optional +#depends and configuration questions in a random manner instead of doing +#the default + DO_DEFAULTS=${DO_DEFAULTS:=yes} + +#If this is yes pm-test will run pm-report-snap after each run +#if not you must run it by other means +#in either case it will do all unreported snapshots +RUNTIME_REPORT=${RUNTIME_REPORT:=yes} + + +#places prometheus wont touch +PRUNE_PATHS=".*sorcery.* /boot/.* /dev/.* /devices/.* /root/.* /home/.* /proc/.* /sys/.* /tmp/.* /mnt/.* $PMDIR/.* /etc/prometheus/.* /usr/src/.* /etc/pm-config /var/log/.* /etc/ld.so.cache /var/run/.* /var/spool/mail/.* /var/cache/compiler/.* /usr/man/.* /usr/share/prometheus/.* /lib/modules/.* /usr/sbin/pm-.*" + +#sorcery files in /usr/sbin/... +PRUNE_SORCERY="/usr/sbin/cast /usr/sbin/gaze /usr/sbin/dispel /usr/sbin/scribe /usr/sbin/summon /usr/sbin/scribbler" + +#adjust this (in the local config file) for any local issues you may have +#with protecting files +PRUNE_LOCAL=${PRUNE_LOCAL:=""} + +#send a report to bugzilla + +REPORT_BUGZILLA=${REPORT_BUGZILLA:=no} + +#email report somewhere + +REPORT_MAIL=${REPORT_MAIL:=yes} +REPORT_ADDRESS=${REPORT_ADDRESS:="root@localhost"} + +#email success reports too (lets you know its working) +#this will not send things to bugzilla +#no success report will (should) ever be sent to bugzilla, +#since its not a bug! +REPORT_SUCCESS=${REPORT_SUCCESS:=yes} + + + +#BUGCLI STUFF: +#you need a bugzilla account +#PLEASE OVVERIDE THESE + BUGZILLA_USER=${BUGZILLA_USER:="j@random.net"} + export BUGCLI_PASSWORD=${BUGCLI_PASSWORD:="wrong_passwd"} + +#tailor the following as needed + export BUGCLI_PRODUCT=${BUGCLI_PRODUCT:="Prometheus"} +#in pm-test section this can be changed to the section name +export BUGCLI_COMPONENT=${BUGCLI_COMPONENT:="Unknown"} +#override this + export BUGCLI_VERSION=${BUGCLI_VERSION:="test grimoire"} + export BUGCLI_PRIORITY=${BUGCLI_PRIORITY:="P2"} + export BUGCLI_PLATFORM=${BUGCLI_PLATFORM:="x86"} + export BUGCLI_OS=${BUGCLI_OS:="Linux"} + export BUGCLI_SEVERITY=${BUGCLI_SEVERITY:="normal"} + export BUGCLI_SERVER=${BUGCLI_SERVER:="bugs.sourcemage.org"} +export BUGCLI_DIRECTORY=${BUGCLI_DIRECTORY:="/"} + @@ -0,0 +1,4 @@ +cp -v etc/pm-config $1/etc +cp -v usr/sbin/* $1/usr/sbin/ +mkdir -p $1/usr/share/prometheus 2>/dev/null +cp usr/share/fprotect.lst $1/usr/share/prometheus @@ -0,0 +1,120 @@ +lists: + +ignore.lst + do not cast or dispel these for any reason whatsoever + do not modify, this is for the user to handle + note: deal with triggers + +problems.lst + update in pm-post-cast + casts that failed, remove when there is a new version pm-update + +installed.lst + list of thigns installed during pm-pre-cast + update uncast.lst with it + use for finding out what installed during pm-test-cast in pm-post-cast + do not dispel anything on this list + +excluded.lst + the cat of the above three lists + +uncast.lst + things on the queue +known.lst + everything that could be on the queue + +currcast.lst +success.lst +failure.lst + +missing.lst ??? + +deleted.lst +new.lst +different.lst +usrlocal.lst + +fprotect.lst files to not report a problem about even if they are + new/different/deleted + +files: +md5sum_image + md5sum of every file in the 'image' +currtime + magic time constant that this test will use for archival purposes +state + what phase we were last in: (name of the script) +unreported + snapshots that havent been reported on yet +reported + log of things being reported + +dir-tree: +/etc/pm-config +/usr/doc/tinderbox/... +/tinderbox/ +/tinderbox/state +/tinderbox/currtime +/tinderbox/md5sum_image +/tinderbox/image/... +/tinderbox/lists/... +/tinderbox/snapshot/<time>/... +/tinderbox/save +/tinderbox/unreported + +scripts: + +pm-config (sh) + sourced by things + +high level: +pm-setup + build the initial environment + +pm-test [forever|once|grimoire|until] (sh) + this is a high level entry point, used by users, runs eternally + or once (nightly), or over an entire grimoire once + + ***the entire grimoire once feature has not been written yet + +low level: +pm-build_md5image (sh,done) + make an md5sum of the system as it stands + +pm-update (sh,done) + scribe/sorcery update, rebuilds uncast.lst + update problems.lst + +pm-pre-cast (sh,done) + clean activity log + clean out /usr/src + make installed.lst + +pm-test-cast (perl,done) + splice off part of uncast.lst into currcast.lst + cast it + +pm-post-cast (sh,almost done) + partition off into success and fail lists + archive stuff somewhere + update problems.lst + check for /usr/local + +pm-image-diff (perl, done) + outputs missing new and different files + +pm-restore (sh,done) + dispel success.lst + run pm-build-md5sum on the system + report differences with the old image using pm-image-diff + + restore files from image/remove aliens + +pm-report-all + report on everything in unreported + +pm-seer + awesome reporting + +pm-exclude (perl,done) + take two lists and report what is on the first list but not the second @@ -0,0 +1,2 @@ +locking +cast sections diff --git a/usr/sbin/pm-autocast b/usr/sbin/pm-autocast new file mode 100755 index 0000000..b1c04a8 --- /dev/null +++ b/usr/sbin/pm-autocast @@ -0,0 +1,440 @@ +#!/usr/bin/expect +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## +#options +#1 ignore list +#2 log file +#3 defaults? +#... options to cast -c -r + +set goahead y +set defaults yes + +#######SUBROUTINES############### +#log stuff with pm-autocast: prepended +proc log { str } { + send_log "pm-autocast:$str\n" +} + +#send a y or n if defaults is set to 'y' and send a \r otherwise +proc shrug { } { + global defaults + if { [string match n* $defaults] } { + if { [expr rand()] < 0.5 } { + return y + } else { + return n + } + } else { + return \r + } +} + + +#given a spell name and an ignore file, return 1 if castable +#0 otherwise +proc castable {ignorelist spell} { + if {[lsearch $ignorelist $spell] == -1} { + return 1 + } else { + return 0 + } +} + +#this looks at the input for the next word, which in the callers +#context should be a spellname +proc get_spell {sid} { + expect { + -i $sid + -re "(\[^\n? ]*)" { + set spell [string trim $expect_out(1,string) "\r\n\t "] + log "found: $spell\n" + return $spell + } + } +} + +#grab a word from the input (presumably a spell) +#if that spell is uncastable exit +proc cancast {sid ignorelist spell} { + if { [castable $ignorelist $spell] == 0 } { + log "killing cast because the spell is uncastable" + kill_cast $sid + } +} + +proc kill_cast {sid} { + log "kill_cast" + #send a ctrl-c + send -i $sid "\x03" + #let everyone know we died prematurely + catch { exec touch /tmp/pm-autocast-quit } + #and exit + exit + # nlm +} + +proc fix_deadlock { } { + catch {exec ps -A | grep casting | awk {{print $1}} | tail -1 | xargs kill} +} + +#######################EXPECT ROUTINES################## +#answers all questions for requires +#FIXME: should notice if we've answered a requires question already +#and pick the same one again +proc handle_requires { sid ignorelist requires} { + log "handle_requires" + if {![string length $requires]} { + error "No provider!" + } + global defaults + global requires_lookup + set length 0 + set lst { } + log "running handle_requires!!\n" + while 1 { + expect { + -i $sid + -re {Continue to use [^yn]*\[[yn]]} { + log "requirement already fulfilled" + send -i $sid y + return + } + -re {(.*?)Which one do you want.\s+\[.]} { + set buffer $expect_out(1,string) + break + } + timeout kill_cast $sid + eof kill_cast $sid + } + } + + array set char_to_spell "" + array set spell_to_char "" + set optional 0 + set optional_idx "" + foreach line [split $buffer \n] { + if {[catch {llength $line}]} { + # oops this line isn't parsable + continue + } + set num [string index [lindex $line 0] 1] + set spell [lindex $line 1] + if {![string length $num] || ![string length $spell]} { + log "empty line on $line" + continue + } + if {[string equal {[none]} $spell]} { + set optional 1 + set optional_idx $num + } elseif {[castable $ignorelist $spell]} { + set char_to_spell($num) $spell + set spell_to_char($spell) $num + } + } + + if {[llength [array names char_to_spell]] == 0} { + if {$optional} { + send -i $sid $optional_idx + } else { + log "ack, none of these are castable!" + kill_cast $sid + } + } else { + if {[string match y* $defaults]} { + send -i $sid \r + } else { + # if an answer was already choosen, try that + if {[info exists requires_lookup($requires)]} { + set prefered_answer $requires_lookup($requires) + if {[info exists spell_to_char($prefered_answer]} { + set answer $spell_to_char($prefered_answer) + } + } + if {![info exists answer]} { + set idx [expr {int(rand()*[llength [array names char_to_spell]])}] + set answer [lindex [array names char_to_spell] $idx] + + set requires_lookup($requires) $char_to_spell($answer) + } + send -i $sid $answer + } + } + expect -i $sid \n { } +} + + +#this jots down md5 issues and records their bug status (input variable) +#and using expect, determines if they are fatal or not +proc md5abort { sid bug spell tarball } { + set out [open /tmp/pm-automd5.lst a] + puts -nonewline $out "$spell:[string trim $tarball ". \n\r"]:$bug:" + expect { + -i $sid + -gl {Abort? \[y]} { + puts $out "fatal" + close $out + send -i $sid \r + kill_cast $sid + } + -gl {Abort? \[n]} { + puts $out "ignored" + close $out + send -i $sid \r + } + } + close $out + error "How did i get here" +} + +#this is supposed to answer all questions from the initial q/a session +proc do_initial { sid ignorelist } { + log "Made it into pm-autocast.do_initial" + while { 1 } { expect { + -i $sid + "is not a spell" { + log "oops, oh well" + } + -re {\n([^\n]*?) preparing environment} { + set spell $expect_out(1,string) + cancast $sid $ignorelist $spell + } + -re {\n([^\n]*?) checking dependencies for} { + set spell $expect_out(1,string) + cancast $sid $ignorelist $spell + } + -re "Install\[^\n]*script\[^\n]*\\\[?]" { + send -i $sid n + } + -re "Enable \[^\n]*script\[^\n]*\\\[?]" { + send -i $sid n + } + -re {Would you like to [^\n]*? the init and/or xinetd script} { + expect { + -i $sid + -gl {Which one do you want} { + # 0 is the "neither" + send -i $sid 0 + } + } + } + -re "\[^\n]*to be the default provider of\[^\n]*\\\[?]" { + send -i $sid n + } + -re "Get \[^\n]* grimoire\?" { + send -i $sid n + expect -i $sid "\n" { } + } + -re {requires some (\S+)[^\n]*?\n} { + handle_requires $sid $ignorelist $expect_out(1,string) + } + "Do you want to use " { + send -i $sid [shrug] + expect -i $sid "\n" { } + } + -re "(Do you want to cast )|(Cast )" { + if { [castable $ignorelist [get_spell $sid]] } { + send -i $sid [shrug] + } else { + send -i $sid n + } + expect -i $sid "\n" { } + } + {Configure host.def} { + send -i $sid n + } + -re {[^\n]*\[.*]} { ;#any random question we dont know + set question $expect_out(0,string) + expect { + -i $sid + -timeout 2 "\n" { + log "$question is not a question" + } + timeout { + send -i $sid [shrug] + } + } + } + -gl "cannot initialize curses" { + log "oops you gave me a menu" + } + "CONTINUE casting" { send -i $sid "y" } + "you want to dispel" { send -i $sid "n" } + -re "Dispel\[^\n]*\?" { send -i $sid "n" } + -re "Spells are to be cast" { + return confirm + } + eof { + log "premature eof" + exit + } + timeout { + send_user "timeout!!! waited too long for something to happen" + #lets shoot something hope it fixes everything + } + }} +} +#this is supposed to watch all the output after casting has started and deal with it correctly. +proc watch_cast {sid} { + #if there is no output for a half hour + #signal a timeout, ie shoot something + #if 60 minutes isnt enough i suppose i can make it configurable + set timeout 3600 + while { 1 } { expect { + -i $sid + timeout + { #something is wrong... + send_user "timeout, oh well..." + exp_continue + #lets shoot something hope it fixes everything + #fix_deadlock + } + -re "Do you wish to add -- options to ./configure\[^\n]*" { + send -i $sid "n" + } + "CONTINUE casting" { send -i $sid "y" } + "you want to dispel" { send -i $sid "n" } + -re "Dispel.*\?" { send -i $sid "n" } + -re {([^:]*): doesn't have an MD5 sum for the uncompressed ([^\n]*)\n} { + md5abort $sid "missing" $expect_out(1,string) $expect_out(2,string) + } + -re {([^:]*): MD5 sum is different for uncompressed ([^\n]*)\n} { + log "different md5sum\n" + md5abort $sid "different" $expect_out(1,string) $expect_out(2,string) + } + -re {([^:]*): MD5 sum was purposefully left out for the uncompressed ([^\n]*)\n[^\n]*\n} { + md5abort $sid "ignored" $expect_out(1,string) $expect_out(2,string) + } + + -re "Shall the .* init script be enabled on install" {send -i $sid "n"} + "Attempt to fix spells that may have become broken" {send -i $sid "n"} + -re {has triggered a .*? on spell} { + expect { + -i $sid + -re {Proceed.\s+\[.]} { send -i $sid "n" } + } + } + -re "Do you want to cast these\[^\n]*\\\[\[yn]]" { + #you already asked me this...must be one of those damn triggers + send -i $sid "n" + } + -re ".* to be the default provider of \[^\n]*\\\[\[yn]]" { send -i $sid "n" } + + #all real patterns should go before this + -re "\[^\n]*\\\[\[yn]]" { + log "read $expect_out(0,string)doing the default\n" + send -i $sid "\r" + } + -re {([^\n]*(\[.*])|(\(.*\))|.*:)} { + #this might be a question or it might not be + #so what we do is wait for 60 seconds for something to go + #with the hope that _something_ on the next line + #will come by, in which case it was a false alarm + set question $expect_out(0,string) + expect { + -i $sid + -timeout 20 "\n" { + #log "$question is not a question" + } + timeout { + #poke + send -i $sid "\n" + } + } + } + -gl {Finished processing install requests} { + expect { + -i $sid + eof { return end } + } + } + -gl {Spells that encountered problems} { + expect { + -i $sid + eof { return end } + } + } + -re "\[^\n]*\n" { } ;#matches anything else keeps timeout from triggering + eof { + log "Premature eof" + return end + #FIXME uh... + } + }} +} + +######REAL CODE########### + +proc main {argv} { + global defaults + set argc [ llength $argv ] + if { $argc < 3 } { + puts "args are not >=3" + exit + } + + set env(TERM) builtin-dump + + set ignore_file [lindex $argv 0] + set fd [open $ignore_file r] + set ignorelist [read $fd] + close $fd + log_file -noappend [lindex $argv 1] + set defaults [ lindex $argv 2 ] + + set spells [lrange $argv 3 end] + + puts "going to cast -r -c $spells" + set cast_pid [spawn cast -r -c $spells] + set sid $spawn_id + + set timeout 180 + set state initial + while 1 { + switch -- $state { + initial { + set state [do_initial $sid $ignorelist ] + continue + } + confirm { + expect { + -i $sid + -re "Do you want to cast these\[^\n]*\\\[\[yn]]" { + send -i $sid y + set state in_cast + continue + } + } + } + in_cast { + set state [watch_cast $sid] + continue + } + end { + exit 0 + } + } + } +} + +# exp_internal 1 +puts "starting" +main $argv +puys "ending" diff --git a/usr/sbin/pm-build-md5image b/usr/sbin/pm-build-md5image new file mode 100755 index 0000000..2e09813 --- /dev/null +++ b/usr/sbin/pm-build-md5image @@ -0,0 +1,27 @@ +#!/bin/bash +################################################################### +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################### + +source /etc/pm-config +#proper credit should go to the slocate guys for this... + + +PRUNE_REGEX=$(echo "$PRUNE_PATHS $PRUNE_SORCERY $PRUNE_LOCAL" |sed -e 's,^,\\\(^,' -e 's, ,$\\\)\\\|\\\(^,g' -e 's,$,$\\\),') +find $1 \( ! \( -type d -o -type b -o -type c -o -type p -o -type s -o -regex $PRUNE_REGEX \) \) -exec md5sum '2>/dev/null' '{}' ';' 2>/dev/null diff --git a/usr/sbin/pm-exclude b/usr/sbin/pm-exclude new file mode 100755 index 0000000..0eccd80 --- /dev/null +++ b/usr/sbin/pm-exclude @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +######################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +############################################################ + +#this prints everything in ARGV[0] that isnt in ARGV[1] +#it is a convenience script for excluding certain lines from files +#please show me a unix utility for this! +open FD1,$ARGV[0] or die; +open FD2,$ARGV[1] or die; +#put everything in FD2 into a hash +$arr2{$_}=1 for(<FD2>); +#read everything from FD1 and if we didnt see it in FD2 print it +map {print if $arr2{$_}!=1 } <FD1> diff --git a/usr/sbin/pm-grab b/usr/sbin/pm-grab new file mode 100755 index 0000000..0d5dcaa --- /dev/null +++ b/usr/sbin/pm-grab @@ -0,0 +1,42 @@ +#!/usr/bin/perl +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## + +#0=file list +#1=number to grab +#srand; + +#read in a list and randomize it in memory +open FD,$ARGV[0] or die "missing $ARGV[0]"; +srand; +while(<FD>){ + my $r = rand @new+1; + push(@new,$new[$r]); + $new[$r] = $_; +} +close FD; +#figure out how many to take +if(exists $ARGV[1]){ + $num=$ARGV[1]-1; +}else{ + $num=0; +} +#print out some number of random things from the list we read in +print @new[0..$num]; diff --git a/usr/sbin/pm-image-diff b/usr/sbin/pm-image-diff new file mode 100755 index 0000000..4bd5b48 --- /dev/null +++ b/usr/sbin/pm-image-diff @@ -0,0 +1,52 @@ +#!/usr/bin/perl +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## +$\="\n"; +sub loadimage{ + my ($input)=@_; + my %hash; + open FD,$input or die; + while(<FD>){ + ($md5,@filename)=split; + $hash{"@filename"}=$md5; + } + close FD; + return %hash; +} + +%old=loadimage($ARGV[0]); +%new=loadimage($ARGV[1]); + +#for all the new files, if the file didnt exist before, remember it +#(because its a new file and should be beaten with reeds) +open FD,">new.lst"; +map{print FD if ! defined $old{$_};} keys %new; +close FD; +#compare md5sums of old files with those of new files +#for all old files, if it is still around and the md5 is different... +#(because the file changed needs fixing (and to be beaten with reeds)) +open FD,">different.lst"; +map {print FD if defined $new{$_} and defined $old{$_} and $new{$_} ne $old{$_}} keys %old; +close FD; +#for all old files that aren't in the list of new files... +#(because we have to restore it...then beat someone with reeds) +open FD,">deleted.lst"; +map{print FD if ! defined $new{$_};} keys %old; +close FD; diff --git a/usr/sbin/pm-post-cast b/usr/sbin/pm-post-cast new file mode 100755 index 0000000..6e32c39 --- /dev/null +++ b/usr/sbin/pm-post-cast @@ -0,0 +1,270 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## + +source /etc/pm-config +source /etc/sorcery/config + +##################################subroutines##################### + +#1 spell name +source_spell(){ + unset SOURCE_DIRECTORY + unset SPELL + unset VERSION + unset UPDATED + codex_set_current_spell_by_name $1 +} + +spell_to_section(){ + section=$(egrep "^$1 " $GRIMOIRE_PATH/$CODEX_CACHE 2>/dev/null| + cut -f2 -d' ' 2>/dev/null| + xargs basename 2>/dev/null) + [ -z $section ] && section=Unknown + echo $section +} + + +#this function creates the success and failure lists +# +#assume that the activity log was previously truncated before +#pm-test-cast was run, future implementations may compare with +#a time stamp +# +#success.lst is defined as anything in the current activity log +#that had success in it at the end, and anything new in +#/var/state/sorcery/packages +# +#failure.lst is defined as anything from the activity log with +#failure or failed in it +split_activity(){ + echo "Splitting casting.lst into success and failure lists." + TMPFILE=/tmp/pm.tmp.$$ + + rm -rf $TMPFILE + + egrep "^[^a-zA-Z]*[ \t]*cast" /var/log/sorcery/activity > $TMPFILE + + #failures from the activity log + egrep "(failure[^\w]*$)|(failed)" $TMPFILE|awk '{print $3}'| + pm-exclude - $IGNORE > /tmp/tfailure.lst + + #successes from the activity log + egrep "success[^\w]*$" $TMPFILE|awk '{print $3;}'|sort|uniq > /tmp/asuccess.lst + + #successes from the packages file + #diff between what sorcery says is installed and the previous packages list + cut -f1 -d: /var/state/sorcery/packages | + pm-exclude - $LIST_DIR/installed.lst > /tmp/psuccess.lst + + #combine the lists, although they should be the same + sort /tmp/psuccess.lst /tmp/asuccess.lst |uniq| + pm-exclude - $IGNORE > $LIST_DIR/success.lst + + # anything we asked to get cast that didnt get installed + # is a failure + for each in `cat $LIST_DIR/currcast.lst`; do + grep -q $each $LIST_DIR/success.lst || echo $each >> /tmp/tfailure.lst + done + sort /tmp/tfailure.lst|uniq > $LIST_DIR/failure.lst + +} + +#1 magic time value +#returns snapshot directory +snap_generic(){ + + local SNAPSHOT=$1 + + #sanity + if [ ! -d $SNAP_DIR ]; then + echo "Uhm...you'r missing a snapshot directory, oh well" + echo "I'll make one anyway" + rm -rf $SNAP_DIR + mkdir -p $SNAP_DIR 2>/dev/null + fi + + ( + mkdir -p $SNAPSHOT + mkdir -p $SNAPSHOT/attachment + mv /tmp/pm-automd5.lst $SNAPSHOT + cp -Rp /etc/sorcery/local/ $SNAPSHOT + cp /var/state/sorcery/packages $SNAPSHOT + cp /var/state/sorcery/depends $SNAPSHOT + bzip2 -c /tmp/cast.log > $SNAPSHOT/attachment/cast.log.bz2 + mv /tmp/cast.err $SNAPSHHOT + ) 2>/dev/null +} + +#both snap_sucess and snap_failure need to have some of the sorcery variables +#defined, so be sure to source /etc/sorcery/config first +#please note: they dont use subroutines of sorcery's, just variable in that +#particular config file + +#1 list path +#2 snapshot path +snap_success(){ + local SNAPSHOT=$1 + local LOG_DIR=/var/log/sorcery + + for each in $(cat $LIST_DIR/success.lst); do + echo "Snapshotting successful cast of $each" + + local SDIR=$SNAPSHOT/success/$each + + mkdir -p $SDIR 2>/dev/null + + mkdir $SDIR/compile 2>/dev/null + mkdir $SDIR/install 2>/dev/null + mkdir $SDIR/md5sum 2>/dev/null + mkdir $SDIR/cache 2>/dev/null + + #this needs to be a function somehow + source_spell "$each" + if [ $SPELL != $each ]; then + echo "$SPELL:$each" >> $SNAPSHOT/conflicted + fi + cp $LOG_DIR/compile/$each-${VERSION}* $SDIR/compile 2>/dev/null + cp $LOG_DIR/install/$each-* $SDIR/install 2>/dev/null + cp $LOG_DIR/md5sum/$each-* $SDIR/md5sum 2>/dev/null + cp $LOG_DIR/cache/$each-* $SDIR/cache 2>/dev/null + done +} + +#1 list path +#2 snapshot dir +snap_failure(){ + local SNAPSHOT=$1 + for each in $(cat $LIST_DIR/failure.lst);do + echo "Snapshotting failed cast of $each" + + local SDIR=$SNAPSHOT/failure/$each + + mkdir -p $SDIR 2>/dev/null + mkdir -p $SDIR/compile 2>/dev/null + + source_spell "$each" + + #sanity... + if [ $SPELL != $each ]; then + echo "$SPELL:$each" >> $SNAPSHOT/conflicted + fi + + md5=$(tar c $SCRIPT_DIRECTORY 2>/dev/null | md5sum|cut -f1 -d' ') + #LOCK + echo $SPELL:$md5 >> $PROBLEMS + #UNLOCK + + if [ ! -e $SOURCE_DIRECTORY ];then + echo "no build directory for $each" + else + tar -czf $SDIR/$each.tar.gz $SOURCE_DIRECTORY + if [ -e $SOURCE_DIRECTORY/config.log ];then + bzip2 -c $SOURCE_DIRECTORY/config.log > $SDIR/attachment/$each-config.log.bz2 + fi + + fi + cp /var/log/sorcery/compile/$each-${VERSION}* $SDIR/compile 2>/dev/null + done +} + +check_usrlocal(){ + echo "checking for /usr/local files" + #files that were there before + grep "/usr/local" $PMDIR/md5sum_image |awk '{print $2}' > /tmp/usrlocal.ok + #files that are there now + find /usr/local \( -type p -o -type s \) -prune -o -type d -o -print >/tmp/usrlocal.found + #if theres nothing in /usr/local at all, return + if [[ ! -s /tmp/usrlocal.found ]]; then return ; fi + + #otherwise clear off whats already there from our list + pm-exclude /tmp/usrlocal.found /tmp/usrlocal.ok > $SNAPSHOT/usrlocal.lst + #if theres still something there save it all for later consumption + if [[ -s $SNAPSHOT/usrlocal.lst ]]; then + mkdir -p $SNAPSHOT/usrlocal 2>/dev/null + for each in $(cat $SNAPSHOT/usrlocal.lst );do + echo "$each should not be in /usr/local" + mkdir -p usrlocal/$(dirname $each) 2>/dev/null + cp $each $SNAPSHOT/usrlocal/ + done + fi + rm /tmp/usrlocal.* +} +###########################end-subroutines##################### +###########################begin real code##################### + +#override from defaults +#sanity checks +#FIXME make a library for this +if ! grep -q "pm-test-cast:stop" $PMDIR/state ; then + echo "Uhm...are you sure you just ran pm-test-cast?" + if [ ! -e $LIST_DIR/currcast.lst ];then + echo "Geez you dont even have a currcast.lst!" + echo "What do you take me for?" + exit 1 + fi + yn='n' + read -p "do you want to continue? y/n" -t 60 yn + if [[ ! $yn=='y' ]]; then + exit 1 + fi +fi +echo "pm-post-cast:start" > $PMDIR/state + + + +if [ ! -e $PMDIR/currtime ];then + echo "Uhm...there isnt a currtime file, oh well" + echo "I'll make one anyway" + date +%Y%m%d%H%M > $PMDIR/currtime +fi +currtime=$(cat $PMDIR/currtime) + +#real stuff +split_activity + +#new list "WINNER" list any and all spells that successfully cast at least once +#someday a script will synthesize winner lists into a pretty listing with +#frequencies +touch $WINNER +cat $LIST_DIR/success.lst >> $WINNER +cat $LIST_DIR/failure.lst >> $LOSER + + +echo "Make snapshot of cast" +SNAPSHOT="$SNAP_DIR/$currtime" +snap_generic "$SNAPSHOT" + +#determine the component +if [ -e $LIST_DIR/failure.lst ] ; then + spell_to_section $(head -1 $LIST_DIR/failure.lst)> $SNAPSHOT/component +else + spell_to_section $(head -1 $LIST_DIR/currcast.lst)> $SNAPSHOT/component +fi + +source /etc/sorcery/config #oh boy...but dont worry, I only want the variables +snap_success "$SNAPSHOT" +snap_failure "$SNAPSHOT" + +check_usrlocal $SNAPSHOT + +echo "pm-post-cast:stop" > $PMDIR/state +exit 0 +###########################end real code######################## diff --git a/usr/sbin/pm-pre-cast b/usr/sbin/pm-pre-cast new file mode 100755 index 0000000..142d0cd --- /dev/null +++ b/usr/sbin/pm-pre-cast @@ -0,0 +1,54 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## +source /etc/pm-config + +#this script cleans up the activity log +#cleans up /usr/src +#and saves the /var/state/sorcery/packages file + + +if [ ! -e $PMDIR/currtime ]; then + echo "Uhm...there isnt a currtime file, oh well" + echo "I'll make one anyway" + date +%Y%m%d%H%M > $PMDIR/currtime +fi +TIME=$(cat $PMDIR/currtime) +echo "pm-pre-cast:start" > $PMDIR/state +if [ -e /var/log/sorcery/activity ]; then + echo "theres still an activity log" + cat /var/log/sorcery/activity >> /var/log/sorcery/activity.old +fi +echo "Making a new activity log" +cat /dev/null > /var/log/sorcery/activity + + +cd /usr/src +echo "Clearing out broken source trees" +ls|egrep -v "^linux"|xargs rm -rf +echo "Clearing /tmp" +rm -rf /tmp/* + +echo "saving packages list" +cp /var/state/sorcery/packages $PMDIR +cut -f1 -d: /var/state/sorcery/packages > $LIST_DIR/installed.lst + +echo "pm-pre-cast:stop" > $PMDIR/state +exit 0 diff --git a/usr/sbin/pm-report-all b/usr/sbin/pm-report-all new file mode 100755 index 0000000..4b1b808 --- /dev/null +++ b/usr/sbin/pm-report-all @@ -0,0 +1,104 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## +source /etc/pm-config || exit 1 + +clean_old(){ + ls $SNAP_DIR > /tmp/snaps.1 + touch $PMDIR/unreported $PMDIR/save + cat $PMDIR/unreported $PMDIR/save > /tmp/snaps.save 2>/dev/null + + pm-exclude /tmp/snaps.1 /tmp/snaps.save > /tmp/snaps.2 + + if [[ $KEEP_SNAP == "" ]]; then + KEEP_SNAP="1 week" + fi + let deltime=$(date -d "$KEEP_SNAP ago" +%Y%m%d%H%M) + + for each in $(cat /tmp/snaps.2);do + let snaptime=$each + if (( $snaptime < $deltime ));then + echo "deleting snapshot: $snaptime < $deltime" + rm -rf $SNAP_DIR/$each + fi + done +} + +#we move first to slice off any unreported snapshots +#since this can run asynchronously with pm-test + +mv $PMDIR/unreported /tmp/unreported.tmp +sort /tmp/unreported.tmp|uniq > /tmp/unreported +touch $PMDIR/unreported + + +#this is bad...FIXME! +for each in $(cat /tmp/unreported); do + SNAPSHOT=$SNAP_DIR/$each + rm -rf $SNAPSHOT/report.* + echo reporting on $each in $SNAPSHOT + pm-seer --snapshot $each --summary --compile 200 + if [ -s $SNAPSHOT/report.failure ]; then + echo "failure" + [[ -s $SNAPSHOT/title ]] && summary=$(cat $SNAPSHOT/title) || summary="$HOSTNAME:$each" + if [[ $REPORT_BUGZILLA == 'yes' && $(which addbug 2>/dev/null) ]]; then + echo sending $each to bugzilla + ( + echo -n "bugzilla:$each:" + [[ -s $SNAPSHOT/component ]] && BUGCLI_COMPONENT=$(cat $SNAPSHOT/component) + foo=$(addbug --summary "$summary" \ + --description "`cat $SNAPSHOT/report.failure`"\ + --login "$BUGZILLA_USER"| + grep -e '\(Title: Bug .* Submitted\)\|\(bugid: \)\|\(error: \)') + bugid=$(echo $foo|perl -ne "print /([0-9]+)/") + [[ $bugid == "" ]] && echo $each >> /prometheus/report_mia + echo $bugid + + [[ $(which bugattach 2>/dev/null) ]] && + for file in $SNAPSHOT/attachment/* ; do + bar=$(bugattach --login "$BUGZILLA_USER" \ + --description "cast.log.bz2 for $each" \ + --bugid $bugid \ + --filename $file) + echo attachment:$file:$bar + done + )>> $PMDIR/reported + fi +#i hate this feature and want it to go away + if [[ $REPORT_MAIL == 'yes' && + -x /usr/bin/mutt && REPORT_ADDRESS != "" ]] ; then + echo "sending mail" + cat $SNAPSHOT/report.failure | + mutt $REPORT_ADDRESS -s "$summary" + echo "email:$each:$REPORT_ADDRESS" >> $PMDIR/reported + fi + elif [[ -s $SNAPSHOT/report.success && + $REPORT_SUCCESS == 'yes' && + $REPORT_MAIL == 'yes' && + -x /usr/bin/mutt && REPORT_ADDRESS != "" ]] ;then + echo "success" + echo "sending mail" + cat $SNAPSHOT/report.success | + mutt $REPORT_ADDRESS -s "$each prometheus success" + echo "email:$each:$REPORT_ADDRESS" >> $PMDIR/reported + fi +done +rm /tmp/unreported +clean_old diff --git a/usr/sbin/pm-restore b/usr/sbin/pm-restore new file mode 100755 index 0000000..ee8bd95 --- /dev/null +++ b/usr/sbin/pm-restore @@ -0,0 +1,169 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## + + +#########################borrowed/modified from sorcery ################### +filter() { + + if [ -f $1 ]; then + RID_LIST=`for each in $(cat $1); do echo -n "^$each\|"; done + echo -n "/dev/null"` + grep -v "$RID_LIST" + else + cat + fi +} + +fix_list(){ + rm -rf /tmp/$1 + filter $FPROTECT < $1 | + filter $SHARE_DIR/badfiles.lst | + filter /var/lib/sorcery/protected | + filter /var/lib/sorcery/excluded > /tmp/$1 + mv /tmp/$1 . +} + +########################################################## +source /etc/pm-config || exit 10 +if ! grep -q "pm-post-cast:stop" $PMDIR/state ; then + echo "Uhm...are you sure you just ran pm-post-cast?" + if [ ! -e $LIST_DIR/success.lst ] || + [ ! -e $LIST_DIR/failure.lst ];then + echo "Geez you dont even have a currcast.lst!" + echo "What do you take me for?" + exit 1 + fi + yn='n' + read -p "do you want to continue? y/n" -t 60 yn + if [[ ! $yn=='y' ]]; then + exit 1 + fi +fi +echo "pm-restore-cast:start" > $PMDIR/state + +if [ ! -e $PMDIR/currtime ];then + echo "Uhm...there isnt a currtime file, oh well" + echo "I'll make one anyway" + date +%Y%m%d%H%M > $PMDIR/currtime +fi +currtime=$(cat $PMDIR/currtime) + +SNAPSHOT="$SNAP_DIR/$currtime" + +if [ ! -d $SNAPSHOT ]; then + echo "Uhm...theres no snapshot directory: $SNAPSHOT" + echo "Oh well..." + rm -rf $SNAPSHOT + mkdir $SNAPSHOT +fi + +if [ -s $LIST_DIR/success.lst ]; then + echo "dispelling:" + cat $LIST_DIR/success.lst + cat $LIST_DIR/success.lst|xargs dispel --notriggers |tee /tmp/dispellog.$$ + mv /tmp/dispellog.$$ $SNAPSHOT/dispel.log + ldconfig +else + echo "nothing to dispel!" +fi + +echo "Making an md5sum image (this takes a while)" + + +pm-build-md5image / > $SNAPSHOT/md5sum_image + +echo "Finding differences between images" + +cd $SNAPSHOT + +pm-image-diff $PMDIR/md5sum_image $SNAPSHOT/md5sum_image +mkdir deleted diff.old diff.new new 2>/dev/null +rm -f /tmp/badfiles.lst +touch /tmp/badfiles.lst +touch $SHARE_DIR/badfiles.lst + +old_ifs=$IFS +IFS=" +" + +echo "Fixing changed files" +if [ -s different.lst ]; then + rm -f diff.log + for each in $(cat different.lst );do + echo "$each was changed, restoring old and saving new" + mkdir -p diff.new/$(dirname $each) 2>/dev/null + cp $each diff.new/$each + mkdir -p diff.old/$(dirname $each) 2>/dev/null + cp $PMDIR/image/$each diff.old/$each + mkdir -p $(dirname $each) 2>/dev/null + cp $PMDIR/image/$each $each + ( echo --------$each-------- + diff diff.old/$each diff.new/$each + ) >> diff.log + done + fix_list different.lst + cat different.lst >> /tmp/badfiles.lst +fi + +echo "Restoring deleted files" +if [ -s deleted.lst ]; then + for each in $(cat deleted.lst );do + echo "$each is deleted, restoring" + mkdir -p deleted/$(dirname $each) 2>/dev/null + cp $PMDIR/image/${each} deleted/$each + mkdir -p $(dirname $each) 2>/dev/null + cp $PMDIR/image/$each $each + done + fix_list deleted.lst + cat deleted.lst >> /tmp/badfiles.lst +fi + +#this needs to happen last +#or else bad things happen +echo "Removing new files" +if [ -s new.lst ]; then + for each in $(cat new.lst ); do + echo "$each is a new file, fixing..." + mkdir -p $(dirname $each) 2>/dev/null + mv $each new + rdir=$(dirname $each) + while (rmdir $rdir 2> /dev/null); do + rmdir=$(dirname $rdir) + done + done + fix_list new.lst + cat new.lst >> /tmp/badfiles.lst +fi +IFS=$old_ifs + +cat $SHARE_DIR/badfiles.lst >> /tmp/badfiles.lst +sort /tmp/badfiles.lst|uniq > $SHARE_DIR/badfiles.lst +rm /tmp/badfiles.lst + +ldconfig + +echo "Copying lists to snapshot" +cp -Rp $PMDIR/lists $SNAPSHOT +echo "Saving activity log" +mv /var/log/sorcery/activity $SNAPSHOT +echo "adding snapshot to list of unreported snapshots" +echo $currtime >> $PMDIR/unreported +echo "pm-restore-cast:stop" > $PMDIR/state diff --git a/usr/sbin/pm-seer b/usr/sbin/pm-seer new file mode 100755 index 0000000..5c87327 --- /dev/null +++ b/usr/sbin/pm-seer @@ -0,0 +1,667 @@ +#!/usr/bin/perl +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Duane Malcolm d.malcolm@auckland.ac.nz +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## + +#todo: +# remove useless options +# make summon fail list +# title +# clean up config/option crap... +# output trimming +# + +# Seer is a reporting tool for prometheus. + +sub seer_usage { + print STDOUT << "END_OF_HELP"; +Seer is a reporting tool prometheus output. + +Function: + --summary : implies all other reporting options in the order they appear + --snapshot <snapshot> : snapshot name + --output <output dir> : full path to output dir (default is snapshot dir) + --bzip2 : bzip2 the final report + +reporting options: + --coord : the where and then when + --hls : make a high level summary + + --analysis : try to say something intelligent + --lists : reports current, failure and success lists + --md5 : lists the md5sum problems encountered if any + + --activity : reports activity + --depends : lists dependency settings + --grimoires : reports grimoires installed and their ordering + --system : reports system and prometheus settings + --installed : lists things installed (a bit redundant) + + + --compile <#lines|full> : reports #line or all of compile log + + --badfiles : report files that were deleted, left, or changed + --usrlocal : files that somehow ended up in /usr/local + +END_OF_HELP +} + + +# Perl tips: +# - map { print $_; } @list; to print a list +# - for @list { print $_;} +# - read a file into a list like this: @list=<FILE>; +# - print "looping" while(1); +# - set the field seperator: $" +# - end of a list seperator: $\ +# - $CONFIG{"current_list"}=$CONFIG{lists_dir}/currcast.lst"); + + +#DEFAULTS +%CONFIG=('compile_lines',40, 'config_lines','full', 'max_size',65536, 'help',0); +seer_initialize(); +seer_parse(); +if($CONFIG{"help"}){ + seer_usage(); + exit 1; +} elsif(!defined $CONFIG{snapshot_name}){ + print "You need to give me a snapshot"; + exit 1; +} +seer_build_config(); +main(); + +################### +### SUBROUTINES ### +################### +sub seer_build_config(){ + #this is where the snapshot is located + $CONFIG{"snapshot_dir"} ="$PMCONFIG{SNAP_DIR}/$CONFIG{snapshot_name}"; + $CONFIG{"output_dir"} ="$CONFIG{snapshot_dir}" + if (! defined $CONFIG{output_dir}); + + #files and stuff + $CONFIG{"current_list"} ="$CONFIG{snapshot_dir}/lists/currcast.lst"; + $CONFIG{"success_list"} ="$CONFIG{snapshot_dir}/lists/success.lst"; + $CONFIG{"failure_list"} ="$CONFIG{snapshot_dir}/lists/failure.lst"; + $CONFIG{"config_file"} ="$CONFIG{snapshot_dir}/local/config"; + $CONFIG{"grimoire_file"} ="$CONFIG{snapshot_dir}/local/grimoire"; + $CONFIG{"activity_file"} ="$CONFIG{snapshot_dir}/activity"; + $CONFIG{"compile_logs"} ="$CONFIG{snapshot_dir}/failure"; + $CONFIG{"config_logs"} ="$CONFIG{snapshot_dir}/failure"; + $CONFIG{"installed_file"} ="$CONFIG{snapshot_dir}/packages"; + $CONFIG{"depends_file"} ="$CONFIG{snapshot_dir}/depends"; + + #stuff for bad files + $CONFIG{"old_list"} ="$CONFIG{snapshot_dir}/old.lst"; + $CONFIG{"new_list"} ="$CONFIG{snapshot_dir}/new.lst"; + $CONFIG{"diff_list"} ="$CONFIG{snapshot_dir}/different.lst"; + $CONFIG{"diff_log"} ="$CONFIG{snapshot_dir}/diff.log"; + $CONFIG{"usrlocal_list"} ="$CONFIG{snapshot_dir}/usrlocal.lst"; + $CONFIG{"pm_automd5"} ="$CONFIG{snapshot_dir}/pm-automd5.lst"; +} + +sub main() { + seer_read(); + + if(defined %ERROR){ + $CONFIG{output_file}="$CONFIG{output_dir}/report.failure"; + open FILE, ">$CONFIG{output_dir}/title" or + die "Error: Can't open $CONFIG{output_dir}/title\n"; + seer_write_title() if($CONFIG{title}); + close FILE; + }else{ + $CONFIG{output_file}="$CONFIG{output_dir}/report.success"; + } + + $not_done = 1; + while($not_done) { +print "in loop"; + seer_write(); +print "did write"; + $total = 0; + map { $total += $LINES{$_}} keys %LINES; +print "$total"; + if ( $total > $CONFIG{max_size} ) { +print "doing the trim"; + seer_trim(); + } else { + $not_done = 0; + } + } + + if($CONFIG{bzip2}){ + `bzip2 -f $CONFIG{output_file}`; + } +} + +sub seer_initialize{ + #source the config file and then output all the variables + #store the output in $foo + my $foo=`bash -norc -noprofile -c "source /etc/pm-config 2>/dev/null && set"`; + if ($?!=0){ + seer_usage(); + exit 1; + } + map{ + ($key,$value)=split "=",$_; + $PMCONFIG{$key}=$value; + }split "\n",$foo; +} + + +sub seer_parse{ + for($i=0;$i<=@ARGV;$i++){ + if($ARGV[$i]=~/^--summary/){ + %CONFIG=(%CONFIG, coord,1, hls,1, analysis,1, activity,1, lists,1, + installed,1, depends,1, "system",1, "local",1, + grimoires,1, compile,1, badfiles,1, + usrlocal,1,md5,1,title,1); + }elsif($ARGV[$i]=~/^--snapshot/){ + if($ARGV[$i+1] ne /--|-/){$CONFIG{snapshot_name}=$ARGV[++$i];}} + elsif($ARGV[$i]=~/^--output/){ + if($ARGV[$i+1] ne /--|-/){%CONFIG=(%CONFIG,"output_dir",$ARGV[++$i]);}} + elsif($ARGV[$i]=~/^--system/){%CONFIG=(%CONFIG,"system",1);} + elsif($ARGV[$i]=~/^--grimoires/){%CONFIG=(%CONFIG,"grimoires",1);} + elsif($ARGV[$i]=~/^--hls/){%CONFIG=(%CONFIG,"hls",1);} + elsif($ARGV[$i]=~/^--coord/){%CONFIG=(%CONFIG,"coord",1);} + elsif($ARGV[$i]=~/^--analysis/){ %CONFIG=(%CONFIG,"analysis",1); } + elsif($ARGV[$i]=~/^--activity/){%CONFIG=(%CONFIG,"activity",1);} + elsif($ARGV[$i]=~/^--lists/){%CONFIG=(%CONFIG,"lists",1);} + elsif($ARGV[$i]=~/^--compile/){ + %CONFIG=(%CONFIG,"compile",1); + if($ARGV[$i+1] ne /--|-/){%CONFIG=(%CONFIG,"compile_lines",$ARGV[$i+1]);++$i;}} + elsif($ARGV[$i]=~/^--installed/){%CONFIG=(%CONFIG,"installed",1);} + elsif($ARGV[$i]=~/^--badfiles/){%CONFIG=(%CONFIG,"badfiles",1);} + elsif($ARGV[$i]=~/^--md5/){%CONFIG=(%CONFIG,"md5",1);} + elsif($ARGV[$i]=~/^--usrlocal/){%CONFIG=(%CONFIG,"usrlocal",1);} + elsif($ARGV[$i]=~/^--depends/){%CONFIG=(%CONFIG,"depends",1);} + elsif($ARGV[$i]=~/^--bzip2/){%CONFIG=(%CONFIG,"bzip2",1);} + elsif($ARGV[$i]=~/^--help/){%CONFIG=(%CONFIG,"help",1);} + } + + return %CONFIG; +} + + +# this code was a crutch and it sucks if i dont need it +# in the next few weeks (today is 4/1), then its going away +sub seer_trim_options{ + #trim config to a number if its 'full' + if($CONFIG{config} and ($OPTIONS{config_lines} eq "full")){ + if($CONFIG{compile} and $CONFIG{compile_lines} ne "full"){ + $CONFIG{config_lines}=$CONFIG{compile_lines}; + }else{ + $CONFIG{config_lines}=160; + } + #trim compile if its 'full' + }elsif($CONFIG{compile} and $CONFIG{compile_lines} eq "full"){ + $CONFIG{compile_lines}=160; + #trim config to less than compile if its bigger, or trim compile + }elsif($CONFIG{compile} and $CONFIG{compile_lines}>0){ + if($CONFIG{config} and $CONFIG{compile_lines}<$CONFIG{config_lines}){ + if($CONFIG{config_lines}>40){ + $CONFIG{config_lines}/=2; + }else{ + $CONFIG{config}=0 + } + }else{ + if($CONFIG{compile_lines}>40){ + $CONFIG{compile_lines}/=2; + }else{ + $CONFIG{compile}=0; + } + } + }elsif($CONFIG{config} and $CONFIG{config_lines}>0){ + if($CONFIG{config_lines}>40){ + $CONFIG{config_lines}/=2; + }else{ + $CONFIG{config}=0 + } + }elsif($CONFIG{config}){ $CONFIG{config}=0; + }elsif($CONFIG{compile}){ $CONFIG{compile}=0; + #if we get this far we are in serious trouble + #basically the number of compile/config logs is so huge + #that we cant make a report, so basically we need to just turn things off + }elsif($CONFIG{depends}){ $CONFIG{depends}=0; + }elsif($CONFIG{grimoires}){ $CONFIG{grimoires}=0; + }elsif($CONFIG{"system"}){ $CONFIG{"system"}=0; + }elsif($CONFIG{md5}){ $CONFIG{md5}=0; + }elsif($CONFIG{badfiles}){ $CONFIG{badfiles}=0; + }elsif($CONFIG{usrlocal}){ $CONFIG{usrlocal}=0; + }elsif($CONFIG{installed}){ $CONFIG{installed}=0; + }elsif($CONFIG{coord}){ $CONFIG{coord}=0; + }elsif($CONFIG{lists}){ $CONFIG{lists}=0; + }elsif($CONFIG{analysis}){ $CONFIG{analysis}=0; + }else{ $CONFIG{max_size}="ignore"; } + #all that remains is the hls, which is a maximum of 4 lines... + #that _cant_ be too big... +} + +#all code related to trimmming options goes here +#this function is also meant to be recalled repeatedly if necessary +#so it has to work in all cases +sub seer_trim{ +print "TRIMING\n"; + + my $max_val = -1; + my $max_name = "compile"; + map { + print "$_ $LINES{$_}\n"; + if ($LINES{$_} > $max_val) { + $max_val=$LINES{$_}; + $max_name=$_; + } + $LINES{$key}=0; + } keys %LINES; + print "The biggest item was $max_name at $max_val\n"; + + if($max_name eq compile) { + if ( $CONFIG{compile_lines} eq full) { + $CONFIG{compile_lines} = 160; + } elsif ( $CONFIG{compile_lines} > 30 ) { + $CONFIG{compile_lines} = int ($CONFIG{compile_lines} * 0.9); + } else { + $CONFIG{compile} = 0; + } + print "Trimming compile size to $CONFIG{compile_lines}\n"; + } elsif ( $max_name eq hdr) { + die "the report is somehow too big when nothing is left but a header"; + } else { + print "Turning off $max_name"; + $CONFIG{$max_name} = 0; + } +} + +############################################## +sub seer_read{ + if($CONFIG{lists}){ seer_read_list(); } + if($CONFIG{activity}){ seer_read_activity(); } + if($CONFIG{depends} or $CONFIG{analysis}){seer_read_depends();} + if($CONFIG{installed} or $CONFIG{analysis}){seer_read_installed();} + if($CONFIG{badfiles}){ seer_read_badfiles(); } + if($CONFIG{md5}){ seer_read_md5(); } + if($CONFIG{usrlocal}){ seer_read_usrlocal(); } + return; +} + +############################################## +sub seer_write{ + open FILE, ">$CONFIG{output_file}" or die "Error: Can't open $CONFIG{output_file}\n"; + $count = 0; + cprint (FILE,"PROMETHEUS REPORT\n\n"); + $LINES{hdr} = $count; $count = 0; + seer_write_hls() if($CONFIG{hls}); + $LINES{hls} = $count; $count = 0; + seer_write_coord() if($CONFIG{coord}); + $LINES{coord} = $count; $count = 0; + seer_write_lists() if($CONFIG{lists}); + $LINES{lists} = $count; $count = 0; + seer_write_analysis() if($CONFIG{analysis}); + $LINES{analysis} = $count; $count = 0; + seer_write_compile() if($CONFIG{compile}); +print "COMPILE COUNT IS $count\n"; + $LINES{compile} = $count; $count = 0; + seer_write_badfiles() if($CONFIG{badfiles}); + $LINES{badfiles} = $count; $count = 0; + seer_write_md5() if($CONFIG{md5}); + $LINES{md5} = $count; $count = 0; + seer_write_usrlocal() if($CONFIG{usrlocal}); + $LINES{usrlocal} = $count; $count = 0; + seer_write_system() if($CONFIG{system}); + $LINES{system} = $count; $count = 0; + seer_write_activity() if($CONFIG{activity}); + $LINES{activity} = $count; $count = 0; + seer_write_grimoire() if($CONFIG{grimoire}); + $LINES{grimoire} = $count; $count = 0; + seer_write_depends() if($CONFIG{depends}); + $LINES{depends} = $count; $count = 0; + seer_write_installed() if($CONFIG{installed}); + $LINES{installed} = $count; $count = 0; + close FILE; +} + +######################################## +################# +#seer_read stuff# +################# + +sub seer_read_list{ + open FILE, "<$CONFIG{current_list}"; + @CURRENT_LIST=<FILE>; + close FILE; + open FILE, "<$CONFIG{success_list}"; + @SUCCESS_LIST=<FILE>; + close FILE; + open FILE, "<$CONFIG{failure_list}"; + @FAILURE_LIST=<FILE>; + close FILE; + $ERROR{cast}=@FAILURE_LIST if (@FAILURE_LIST); +} + + +sub seer_read_activity{ + open FILE, "<$CONFIG{activity_file}"; + while (<FILE>){ + ($date,$task,$spell,$version,$result,$info)=(/\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)/); + my @foo=($result,$task,$spell,$version,$info); + push @ACTIVITY,\@foo; + } + close FILE; +} + +sub seer_read_depends{ + open FILE, "<$CONFIG{depends_file}"; + @depends=<FILE>; + close FILE; +} +sub seer_read_installed{ + open FILE, "<$CONFIG{installed_file}"; + @installed=<FILE>; + close FILE; +} + + +#since its of no use atm to waste memory sucking this in, im just going +#to set some flags and refer to them later +#XXXX +sub seer_read_badfiles{ + if( -s $CONFIG{new_list}){ + open FILE, "<$CONFIG{new_list}"; + @new_files=sort <FILE>; + $ERROR{new_files}=@new_files; + close FILE + } + if( -s $CONFIG{old_list}){ + open FILE, "$CONFIG{old_list}"; + @old_files=sort <FILE>; + $ERROR{old_files}=@old_files; + close FILE + } + if( -s $CONFIG{diff_list}){ + open FILE, "$CONFIG{diff_list}"; + @diff_files=sort <FILE>; + $ERROR{diff_files}=@diff_files; + close FILE + } +} + +sub seer_read_usrlocal{ + if( -s $CONFIG{usrlocal_list}){ + open FILE, "$CONFIG{usrlocal_list}"; + @usrlocal_files=<FILE>; + $ERROR{usrlocal}=@usrlocal_files; + close FILE + } +} + + +sub seer_read_md5{ + open FILE, "<$CONFIG{pm_automd5}"; + @md5probs=<FILE>; + foreach $bar (@md5probs){ + if($bar=~/.*:.*:(missing)|(different):*/){ + $ERROR{md5}++; + } + } + close FILE; +} + +################## +#seer_write stuff# +################## +sub seer_write_title{ + my $hostname=`hostname`; + chomp $hostname; + + #Theres more than one way to do it. + #and I'll be damned if Im going to set and then check a variable + #when a goto will suffice, besides I like control flow to hold conditions + for($i=0;$i<@ACTIVITY;$i++){ + ($result,$task,$spell,$version,$info)=@{$ACTIVITY[$i]}; + if ($task =~ /summon/ and $result =~ /fail/) { + print FILE "summon failure $spell"; + goto end; + } + elsif ($task =~ /cast/ and $result =~ /fail/) { + print FILE "cast failure $spell"; + goto end; + } + } + $spell=$CURRENT_LIST[0]; + chomp $spell; + foreach $key (sort keys %ERROR) { + if($key eq "md5") { + print FILE "$ERROR{$key} md5sum problems"; goto end; + } elsif($key eq "new_files"){ + print FILE "$ERROR{$key} file(s) left behind from $spell"; goto end; + } elsif($key eq "old_files"){ + print FILE "$ERROR{$key} file(s) removed from $spell"; goto end; + } elsif($key eq "diff_files"){ + print FILE "$ERROR{$key} file(s) changed from $spell"; goto end; + } elsif($key eq "usrlocal"){ + print FILE "$ERROR{$_} file(s) in /usr/local from $spell"; goto end; + } + } + end: + print FILE ":$hostname:$CONFIG{snapshot_name}\n"; +} + +sub seer_write_hls{ + cprint (FILE, "HIGH LEVEL SUMMARY:\n"); + if( defined %ERROR ){ + map{ + if($_ eq "cast"){ + $foo=@FAILURE_LIST; + cprint (FILE, " At least $foo cast(s) failed.\n"); + } + cprint (FILE, " At least $ERROR{$_} md5sum problems occured.\n") if($_ eq "md5"); + cprint (FILE, " At least $ERROR{$_} file(s) left behind after the dispel.\n") if($_ eq "new_files"); + cprint (FILE, " At least $ERROR{$_} file(s) removed after a dispel when it shouldnt have.\n") if($_ eq "old_files"); + cprint (FILE, " At least $ERROR{$_} file(s) left changed after the dispel.\n") if($_ eq "diff_files"); + cprint (FILE, " At least $ERROR{$_} file(s) placed in /usr/local after a cast.\n") if($_ eq "usrlocal"); + } sort keys %ERROR + }else{ + cprint (FILE, "I found no problems.\n"); + } + cprint (FILE, "\n\n"); + +} + +sub seer_write_coord{ + cprint (FILE,"PROMETHEUS COORDINATES:\n"); + cprint (FILE,`hostname`); + cprint (FILE,"$CONFIG{snapshot_name}\n\n"); +} + +sub seer_write_analysis{ + if($CONFIG{analysis}){ + %DONE=(); + cprint (FILE,"SUMMARY:\n"); + for($i=0;$i<@ACTIVITY;$i++){ + ($result,$task,$spell,$version,$info)=@{$ACTIVITY[$i]}; + if (($task =~ /cast/) and ($DONE{"$spell $version"} ne 1)){ + %DONE=(%DONE,"$spell $version",1); + cprint (FILE,"$result $spell-$version $info\n"); + for($j=0;$j<@depends;$j++){ + if($depends[$j]=~/^\Q$spell:/){ + ($depends_name,$state,$depend_type)=($depends[$j]=~/\s*\w+:(\S+):(\S+):(\w+).*/); + $installed_spell="not"; + for($k=0;$k<@installed;$k++){ + ($name)=($installed[$k]=~/(\S+):\d+:\w+/); + if($depends_name eq $name){ + ($installed_spell,$date,$installed_state,$installed_version)=($installed[$k]=~/\s*(\S+):(\d+):(\w+):(\S+).*/); + } + } + if($installed_spell eq "not"){ + cprint (FILE," $depend_type($state): $depends_name [not installed]\n"); + }else{ + cprint (FILE," $depend_type($state): $depends_name [$installed_spell-$installed_version $installed_state($date)]\n"); + } + } + } + } + } + cprint (FILE,"\n\n"); + } +} + +sub seer_write_system{ + if($CONFIG{system}){ + cprint (FILE,"SYSTEM SETTINGS:\n"); + map { + if(/SORCERY_BRANCH|ARCHITECT|OPTIM/){ + cprint (FILE," $_=$SYSTEM{$_}\n");} + } keys %SYSTEM; + cprint (FILE,"\n"); + cprint (FILE,"LOCAL SETTINGS:\n"); + map{ + if((/KEEP_SNAP|GRIMOIRE|NUM_CAST|MACHTYPE|DO_DEFAULTS/)){ + cprint (FILE," $_ = $PMCONFIG{$_}\n"); + } + }keys %PMCONFIG; + cprint (FILE,"\n\n"); + } +} + +sub seer_write_grimoire{ + if($CONFIG{grimoire}){ + cprint (FILE,"GRIMOIRES:\n"); + map{ cprint (FILE, " $_\n"); } @grimoires; + cprint (FILE, "\n\n"); + } +} + +sub seer_write_activity{ + if($CONFIG{activity} or $CONFIG{summary}){ + cprint (FILE,"ACTIVITY LOG:\n"); + map{ cprint (FILE," @$_\n"); }@ACTIVITY; + cprint (FILE, "\n\n"); + } +} + +sub seer_write_lists{ + if($CONFIG{lists} or $CONFIG{summary}){ + cprint (FILE,"CURRENT LIST:\n"); + map { cprint (FILE," $_"); } @CURRENT_LIST; + cprint (FILE,"\n\n"); + cprint (FILE,"FAILURE LIST:\n"); + map { cprint (FILE," $_"); } @FAILURE_LIST; + cprint (FILE,"\n\n"); + cprint (FILE,"SUCCESS LIST:\n"); + map { cprint (FILE," $_"); } @SUCCESS_LIST; + cprint (FILE,"\n\n"); + } +} + +sub seer_write_compile{ + if($CONFIG{compile}){ + cprint (FILE,"COMPILE LOGS: \n"); + @files=glob ("$CONFIG{compile_logs}/*/compile/*bz2"); + foreach $file (@files){ + @compile_log = `bzcat $file`; + ($file)=($file=~/\S*\/(\S+)$/); #wtf + $file_length=@compile_log; + if($CONFIG{compile_lines}=~/full/){ + $start=0; + } else{ + $start=$file_length-$CONFIG{compile_lines}; + if ($start<0){$start=0;}; + } + cprint (FILE,"\nCOMPILE LOG: $file [Lines: $start-$file_length]\n\n"); + + for($i=$start;$i<=$file_length;$i++){ + cprint (FILE,"$compile_log[$i]"); + } + cprint (FILE,"\n"); + } + cprint (FILE,"\n"); + } +} + + +sub seer_write_installed{ + if($CONFIG{installed}){ + cprint (FILE,"INSTALLED SPELLS:\n"); + @installed=sort(@installed); + map { cprint (FILE," $_"); } @installed; + cprint (FILE,"\n\n"); + } +} + +sub seer_write_depends{ + if($CONFIG{depends}){ + my %SPELLHASH; + map{ + chomp; + $SPELLHASH{$_}=1; + } (@SUCCESS_LIST,@FAILURE_LIST); + cprint (FILE,"DEPENDENCIES:\n"); + map{ + ($spell,$depend,$value,$type,$option_on,$option_off)=split ':'; + if($SPELLHASH{$spell}==1 or $SPELLHASH{$depend}==1){ + cprint (FILE,$_); + } + }sort @depends; + cprint (FILE,"\n\n"); + } +} + +sub seer_write_badfiles{ + if($ERROR{new_files}){ + cprint (FILE,"FILES OF UNKNOWN ORIGIN:\n"); + cprint (FILE,"@new_files"); + cprint (FILE,"\n"); + } + if($ERROR{old_files}){ + cprint (FILE,"\nMISSING FILES:\n"); + cprint (FILE,"@old_files"); + cprint ("\n"); + } + if($ERROR{diff_files}){ + cprint (FILE,"\nCHANGED FILES:\n"); + cprint (FILE,"@diff_files"); + cprint (FILE,"\n"); + } +} + +sub seer_write_md5{ + if(defined @md5probs){ + cprint (FILE,"PROBLEMS WITH MD5SUMS\n"); + cprint (FILE,"@md5probs"); + cprint (FILE,"\n\n"); + } +} + +sub seer_write_usrlocal{ + if($CONFIG{usrlocal} and $ERROR{usrlocal}){ + cprint (FILE,"/USR/LOCAL FILES:\n"); + cprint (FILE ,"@usrlocal_files"); + cprint (FILE,"\n\n"); + } +} + + +sub cprint{ + ($FH,$out)=@_; + $retval=print $FH $out; + $count+=length $out; + return $retval; +} diff --git a/usr/sbin/pm-setup b/usr/sbin/pm-setup new file mode 100755 index 0000000..f775f3b --- /dev/null +++ b/usr/sbin/pm-setup @@ -0,0 +1,74 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## + +if [ -e /etc/pm-config ];then + source /etc/pm-config +else + echo "no config file! incomplete install? FIXME" + exit 1 +fi +echo "" +echo "I am going to take an image of your system," +echo "please make sure you're system is setup how you want it" +echo "because after this I will use it as a reference point and revert" +echo "back to it as best as I can (and im very good at it)." +echo "" +echo "You can re-run this process later if you really need to change something" +echo "" +yn='n' +read -p "Are you sure everything is the way you want it? y/n" yn +if [[ $yn == 'y' ]]; then + echo Making the directories + mkdir -p $PMDIR $SNAP_DIR $PMDIR/image $LIST_DIR 2>/dev/null + mkdir -p $SHARE_DIR + mkdir -p $UNCAST_DIR + touch $UNCAST + touch $WINNER + touch $KNOWN + touch $PROBLEMS + touch $IGNORE + touch $PMDIR/state + + echo Building an md5sum image of all the important files on your system + pm-build-md5image / | tee $PMDIR/md5sum_image + echo Backing up all those important files + echo I will do my best to keep the system looking like this, make sure + echo all your config files are the way you want them! + cut -f3 -d' ' $PMDIR/md5sum_image|sed 's/ /\\ /'|cpio -p -dmVau $PMDIR/image +#LOCK + echo Making a list of spells to ignore, feel free to edit + echo "$IGNORE" + echo Under no circumstances will anything in this list be cast + echo or dispelled either excplicitly or implicitly + cp $IGNORE /tmp/ignore.lst + cat /var/lib/sorcery/sustained >> /tmp/ignore.lst + cut -f1 -d: /var/state/sorcery/packages >> /tmp/ignore.lst + grep kernel $GRIMOIRE_PATH/$CODEX_CACHE|cut -f1 -d' ' >> /tmp/ignore.lst + sort /tmp/ignore.lst|uniq > $IGNORE + touch $FPROTECT + sort /usr/share/prometheus/fprotect.lst $FPROTECT|uniq > /tmp/fp.lst + mv /tmp/fp.lst $FPROTECT +#UNLOCK + +else + echo Please run pm-setup when you are actually ready +fi + diff --git a/usr/sbin/pm-test b/usr/sbin/pm-test new file mode 100755 index 0000000..ce571e1 --- /dev/null +++ b/usr/sbin/pm-test @@ -0,0 +1,227 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## +source /etc/pm-config + +#initially do an update (as no recent cast failed) +#FIXME (optionalize this) +SKIP_UPDATE=0 + +usage(){ +cat << EOF +This is the front end to prometheus +it will in one of several modes: + +once run through a cast/dispel cycle once, then exit + +once spell cast spell, useful for debugging, or testing just + one particular spell + +forever run through cast/dispel cycles indefinitly or + until the stop file appears in the $PMDIR/stop + +grimoire this is exactly like forever except it stops + once it has picked everything in the grimoire + +until time this will continue running until <time> in the future + time must be something parsable by the date program + +section name this will cast everything in a section, or at least + attempt to. (if a dependancy breaks and multiple spells + depend on it, none of them will get cast). +EOF +} + +check_val() { + if [[ $1 != 0 ]] ; then + echo "we have a problem," + echo "please remember what messages you have recieved" + echo "and email astitt@sourcemage.org a bug report" + exit 1 + fi +} + +#here we expect to be in whatever environment is necessary for this to work +#be it chroot, native or uml, assume all the normal stuff should work +#we also expect that the list that our first argument is a non-empty list +#of spells to cast +#that list will be adjusted by the end of this function +cast_dispel_cycle(){ + #re-source to update dynamically + local UNCAST=$1 + shift + source /etc/pm-config + if [[ $CLEAR_SPOOL == "yes" ]]; then + echo "Cleaning /var/spool/sorcery/* for you" + rm -f /var/spool/sorcery/* 2>/dev/null + fi + if [ ! -e $PMDIR/md5sum_image ]; then + echo "Uhm...where is your md5sum_image?" + echo "oh well I'll make one for you anyways, hang on." + pm-build-md5image / > $PMDIR/md5sum_image + check_val $? + echo "got that taken care of..." + fi + + currtime=$(date +%Y%m%d%H%M) + echo $currtime > $PMDIR/currtime + + #truncate activity log + if [ -e /var/log/sorcery/activity ]; then + cat /var/log/sorcery/activity >> /var/log/sorcery/activity.old + rm /var/log/sorcery/activity + touch /var/log/sorcery/activity + fi + if [[ $DO_UPDATES == "yes" && $SKIP_UPDATE != 1 ]]; then + echo "running pm-update" + echo "this will download new stuff" + #it also ensures + pm-update + check_val $? + else + echo "skipping update" + fi + echo "running pm-pre-cast" + pm-pre-cast + check_val $? + rm -rf /tmp/pm-autocast-quit + echo "running pm-post-cast" + echo pm-test-cast -s $UNCAST $* + pm-test-cast -s $UNCAST $* + check_val $? + if [[ -e /tmp/pm-autocast-quit && ! -s /tmp/pm-automd5.lst ]];then + echo "pm-autocast quit early" + echo "I think I'll stop now" + SKIP_UPDATE=1 + return + fi + echo "okay got that out of the way" + echo "now to make the first half of the snapshot" + pm-post-cast + check_val $? + echo "all right, lets restore the system back to the initial state" + echo "and make the second half of the snapshot" + echo "running pm-restore, hold on!" + pm-restore + check_val $? + SKIP_UPDATE=0 +} + +#this actually has a way out +#just make the $PMDIR/stop file exist +cycle_forever(){ + while [ ! -e $PMDIR/stop ]; do + if [[ ! -s $UNCAST ]]; then + #reload + cat $KNOWN > $UNCAST + fi + #FIXME (find section?) + cast_dispel_cycle $UNCAST + [[ $RUNTIME_REPORT == 'yes' ]] && pm-report-all + done + rm -f $PMDIR/stop +} + +cycle_until(){ + stop_time=$(date -d "$*" +%Y%m%d%H%M) || exit 1 + until [[ $stop_time < $(date +%Y%m%d%H%M) || -e $PMDIR/stop ]]; do + if [[ ! -s $UNCAST ]]; then + #reload + cat $KNOWN > $UNCAST + fi + cast_dispel_cycle $UNCAST + [[ $RUNTIME_REPORT == 'yes' ]] && pm-report-all + done + rm -f $PMDIR/stop +} + +#this runs through whatever UNCAST is set to until its empty +#the list must also be non-empty (or else it will just exit +do_list(){ + while [ ! -e $PMDIR/stop ]; do + if [[ ! -s $UNCAST ]]; then + echo "$UNCAST is empty, thats all Im going to do for you" + break + fi + cast_dispel_cycle $UNCAST + [[ $RUNTIME_REPORT == 'yes' ]] && pm-report-all + done + rm -f $PMDIR/stop +} + +#check for a section list, if there is one, make it +#set the bugzilla component +do_section(){ + local section=$1 + local component=$2 + #adjust some globals + UNCAST=$UNCAST_DIR/$section + + if [[ ! -s $UNCAST ]] ; then + echo "the $section uncast list appears to be empty, rebuilding..." + grep $GRIMOIRE_PATH/$section $GRIMOIRE_PATH/$CODEX_CACHE | cut -f1 -d' ' > $UNCAST + fi + echo "There are $(wc -l < $UNCAST) items to be cast" + do_list +} + +check_lock(){ + if [[ -e /var/run/pm.lock ]]; then + echo "it looks like im already running" + yn='n' + read -p "Do you really want to keep going?" yn + if [ $yn != 'y' ];then + exit 1 + fi + else + touch /var/run/pm.lock + fi +} + +#how are we running? +case $1 in + once) check_lock + shift + cast_dispel_cycle $UNCAST $* + ;; +#these next two will automagically update the UNCAST list +#which at this point cannot be + forever) check_lock + cycle_forever + ;; + until) check_lock + shift + cycle_until $* + ;; + grimoire) check_lock + do_list + ;; + section) check_lock + do_section $2 + ;; + list) check_lock + UNCAST=$2 + do_list + ;; + *) usage + exit 1 + ;; +esac +rm /var/run/pm.lock 2>/dev/null diff --git a/usr/sbin/pm-test-cast b/usr/sbin/pm-test-cast new file mode 100755 index 0000000..b26f624 --- /dev/null +++ b/usr/sbin/pm-test-cast @@ -0,0 +1,94 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## +source /etc/pm-config + +echo "pm-test-cast:start" > $PMDIR/state + +CAST_LIST="" + +#heavily borrowed code, thanks sorcery team ;) +while [ -n "$1" ]; do + if echo $1 | grep -q "^-"; then + case $1 in + -s) export UNCAST=$2 ; shift 2 ;; + *) shift 1 ;; + esac + else + CAST_LIST="$CAST_LIST $1" + shift + fi +done + +#LOCK + +#re-generate the excluded list +#which is anything that is in problems, ignore, or installed +#winners are okay (otherwise nothing would get done) +( + cut -f1 -d: $PROBLEMS + cat $IGNORE $LIST_DIR/installed.lst +) |sort|uniq > /tmp/excluded.lst + +#remove anything excluded from the uncast list, this is mostly an optimization +#pm-update will put things back on the uncast lists as they come off of +#the problems list +#FIXME... +pm-exclude $UNCAST /tmp/excluded.lst | +pm-exclude - $WINNER > /tmp/uncast +mv /tmp/uncast $UNCAST + +#this sets currcast.lst to whatever it is we want to cast +#someday this may be more complex, but not today +if [[ -z $CAST_LIST ]]; then + #empty, take something from the uncast list, whatever that may be + pm-grab $UNCAST $NUM_TEST > /tmp/currcast.lst +else + rm -rf /tmp/currcast.lst 2>/dev/null + for each in $CAST_LIST; do echo $each >> /tmp/currcast.lst ; done +fi +#remove what we are going to cast from the uncast list +pm-exclude $UNCAST /tmp/currcast.lst > /tmp/uncast + +#order is important here, we want the currcast.lst copied before we copy in +#the truncated $UNCAST, if we do it the other way, we could lose spells +#this way we could only recast some spells, which is 'okay' + +mv /tmp/currcast.lst $LIST_DIR +mv /tmp/uncast $UNCAST + +#UNLOCK + +#sanity... +echo "making sure color is off in sorcery" +echo "if its on things will break horribly" +cat /etc/sorcery/local/config|sed 's/color *"on"/color "off"/' > /tmp/config +mv /tmp/config /etc/sorcery/local/config + +#cast the stupid thing +cat $PMDIR/lists/currcast.lst| +xargs pm-autocast /tmp/excluded.lst /tmp/cast.log $DO_DEFAULTS +#xargs pm-autocast /tmp/excluded.lst /tmp/cast.log $DO_DEFAULTS +if [[ -e /tmp/pm-autocast-quit ]] ; then + cat $PMDIR/lists/currcast.lst >> $LIST_DIR/skipped.lst +fi + +rm /tmp/excluded.lst +echo "pm-test-cast:stop" > $PMDIR/state diff --git a/usr/sbin/pm-update b/usr/sbin/pm-update new file mode 100755 index 0000000..4717f14 --- /dev/null +++ b/usr/sbin/pm-update @@ -0,0 +1,97 @@ +#!/bin/bash +################################################################## +#Copyright (C) 2003 Andrew Stitt astitt@sourcemage.org +#Copyright (C) 2003 Source Mage GNU/Linux (www.sourcemage.org) +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either +#version 2 of the License, or (at your option) any later +#version. +# +#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, write to the Free Software +#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +################################################################## + + +#todo: make it update all the possible uncast lists +#from UNCAST_DIR + +source /etc/pm-config +if [ ! -d $PMDIR ]; then + rm -rf $PMDIR + mkdir -p $PMDIR 2>/dev/null +fi +if [ ! -d $LIST_DIR ]; then + rm -rf $LIST_DIR + mkdir -p $LIST_DIR 2>/dev/null +fi + +#LOCK +touch $UNCAST +touch $KNOWN + +echo "pm-update:start" > $PMDIR/state + +#sorcery update #this may cause problems +scribe update + +#i really dont like the idea of supporting this +if [[ P4_SYNC == 'yes' && -x $(which p4) ]]; then + p4 sync +fi + +if [ ! -e $GRIMOIRE_PATH/$CODEX_CACHE ];then + echo "Uhm...where is your codex.index file?" + echo "are you testing the wrong grimoire?" + exit 1 +fi + + +#LOCK +echo finding new spells +cut -f1 -d' ' $GRIMOIRE_PATH/$CODEX_CACHE|sort|uniq | +pm-exclude - $IGNORE | +pm-exclude - $KNOWN >/tmp/newspells + +echo "append to uncast and known lists" +sort $KNOWN /tmp/newspells |uniq >/tmp/known.lst +mv /tmp/known.lst $KNOWN + +sort $UNCAST /tmp/newspells |uniq >/tmp/uncast.lst +mv /tmp/uncast.lst $UNCAST + +cp $PROBLEMS $PROBLEMS.backup +. /etc/sorcery/config +rm -rf /tmp/problems.lst +touch /tmp/problems.lst +for each in $(cat $PROBLEMS); do + spell=$(echo $each|cut -f1 -d:) + md5=$(echo $each|cut -f2 -d:) + echo "checking on $spell" + tmp=$(grep "^$spell " -m 1 $GRIMOIRE_PATH/$CODEX_CACHE|cut -f2 -d' ') + if [[ $tmp == "" ]];then + echo "Spell $spell not found" + continue + fi + SCRIPT_DIRECTORY=$tmp/$spell + newmd5=$(tar c $SCRIPT_DIRECTORY 2>/dev/null |md5sum|cut -f1 -d' ') + if [[ $md5 == $newmd5 ]]; then + echo "$spell hasnt changed yet" + echo $spell:$newmd5 >> /tmp/problems.lst + else + echo "$spell has changed removing from list" + echo $spell >> $LIST_DIR/removed.lst + fi +done +mv /tmp/problems.lst $PROBLEMS +#UNLOCK + +echo "pm-update:stop" > $PMDIR/state + diff --git a/usr/share/fprotect.lst b/usr/share/fprotect.lst new file mode 100644 index 0000000..cfdee14 --- /dev/null +++ b/usr/share/fprotect.lst @@ -0,0 +1 @@ +/etc/X11/xdm/Xsession |