import repository from arizona
[raven.git] / apps / stork / storkconfigsync.py
1 #! /usr/bin/env python
2 """
3 <Program Name>
4    storkrepodl.py
5
6 <Started>
7    5-6-09
8
9 <Author>
10    Programmed by .
11
12 <Purpose>
13    Routines for .
14 """
15
16 #           [option, long option,    variable,     action,        data,     default,                            metavar, description]
17 """arizonaconfig
18    options=[
19             ["-C",   "--configfile", "configfile", "store",       "string", "/usr/local/stork/etc/stork.conf", "FILE",   "use a different config file (/usr/local/stork/etc/stork.conf is the default)"]]
20    includes=[]
21 """
22
23 import os
24 import sys
25 import tempfile
26 import arizonageneral
27 import shutil
28 import arizonaconfig
29 import arizonacrypt
30 import arizonareport
31 import arizonatransfer
32 import dircache
33 import random
34 import fnmatch
35 import storkerror
36 import storkrepodl
37 import storkrepolist
38 import storkversion
39 import storkmutex
40 import storkusername
41
42 def fetch_conf():
43     """
44     <Purpose>
45         This function will attempt to download the users
46         configuration file from the stork repository (or whatever
47         repository they specified using the repository option
48
49     <Arguments>
50         None
51
52     <Exceptions>
53         None
54
55     <Side Effects>
56         temp files will be created in /tmp. The users configuration
57         file will also be replaced with the downloaded one if it
58         is succesfull
59     <Returns>
60       True - if we loaded a new conf file and should reload the
61              options
62      False - if we did not replace the configuration file
63     """
64     conffile = arizonaconfig.get_option("configfile")
65     restartFlag = False
66
67     # filename to use for tmpconf file (this is the one that we will
68     # download using curl
69     (tmpconffd, tmpconffile) = tempfile.mkstemp(suffix="configfile.temp")
70     os.close(tmpconffd)
71
72     # Try finally block to remove the tempfile regardless of outcome
73     try:
74       storkrepodl.sync(True, maskList=["conf*.tar.bz2"])
75
76       storkrepolist.init(True, maskList=["conf*.tar.bz2"])
77
78       # SMB: make sure we only find config files named after the slicename,
79       # not after the username
80
81       storkusername.build_key_database(reset=True, ignore_username=True)
82
83       result = storkrepolist.find_file_kind("conf", "stork.conf")
84
85       # SMB: the remainer of stork will use files named after the username,
86       # so reset the key database that we messed with above
87       storkusername.reset_key_database()
88
89       if (not result) or (result[0] == None):
90           arizonareport.send_error(3, "Unable to a locate signed conf file in the repository.")
91           return False
92
93       arizonareport.send_error(3, "Found signed config file: " + str(result[0]))
94       try:
95          arizonacrypt.XML_retrieve_originalfile_from_signedfile(result[0], tmpconffile)
96       except TypeError:
97          arizonareport.send_error(3, "Unable to extract unsigned file from the signed config file that was found.")
98          return False
99
100       # if there's an existing conf file, only overwrite it if the downloaded one is different
101       if os.path.isfile(conffile):
102           try:
103              curhash  = arizonacrypt.get_fn_hash(conffile)
104              newhash  = arizonacrypt.get_fn_hash(tmpconffile)
105           except IOError:
106              arizonareport.send_error(3, "There was an error while comparing your old configuration file")
107
108              # try to figure out why this happened
109              if not os.path.isfile(tmpconffile):
110                 arizonareport.send_error(3, "There was an error while getting the hash of: "+tmpconffile+\
111                                             ", that file does not seem to exist.")
112              elif not arizonageneral.valid_fn(tmpconffile):
113                 arizonareport.send_error(3, "There was an error while getting the hash of: "+tmpconffile+\
114                                             ", that file exists but cannot be read from.")
115
116              arizonareport.send_error(3, "Aborting update of "+conffile+". It will remain unchanged.")
117              return False
118
119           if curhash != newhash:
120               arizonareport.send_error(3, "Downloaded conf file is different than current file, replacing current file.")
121               restartFlag = True
122               shutil.move(conffile, conffile + ".old")
123               shutil.copy(tmpconffile, conffile)
124           else:
125               arizonareport.send_error(3, "Downloaded conf file is the same as the current file.")
126       else:
127           # there was no old config file to contend with, so install our new
128           # one.
129           restartFlag = True
130           shutil.copy(tmpconffile, conffile)
131
132     # clean up the temp file
133     finally:
134        if os.path.exists(tmpconffile):
135            os.remove(tmpconffile)
136
137     return restartFlag
138
139 def sync():
140     run_again = True
141     while (run_again):
142         run_again = False
143
144         try:
145             run_again = fetch_conf()
146         except IOError:
147             arizonareport.send_error(0, "Unable to find usable temp directories: Check permissions/Disk Space")
148             sys.exit(1)
149
150         if run_again:
151             # It's possible that the newly downloaded configuration file might
152             # tell us to look somewhere else for a conf file, so we want to
153             # load the config file into arizonaconfig, and attempt to download
154             # a new one.
155
156             arizonareport.send_out(0, "Loading new config file and re-checking...");
157
158             args = arizonaconfig.init_options("stork.py",configfile_optvar="configfile",version="2.0")
159
160             storkusername.reset_key_database()
161
162 def main(args):
163     """ TODO comment """
164     if arizonaconfig.get_option("noupdateonstart"):
165         arizonareport.send_out(0, "not syncing because --noupdateonstart was specified")
166     else:
167         sync()
168
169 if __name__ == "__main__":
170    try:
171       # use error reporting tool
172       storkerror.init_error_reporting("stork.py")
173
174       # get command line and config file options
175       args = arizonaconfig.init_options("storkreposync.py", configfile_optvar="configfile", version=storkversion.VERREL)
176
177       if os.geteuid() > 0:
178           arizonareport.send_error(0, "You must be root to run this program...")
179           sys.exit(1)
180
181       storkmutex.wait_for_mutex()
182
183       main(args)
184
185    except KeyboardInterrupt:
186       arizonareport.send_out(0, "Exiting via keyboard interrupt...")
187       sys.exit(0)