1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 __doc__='''zenbackup
17
18 Creates backup of zope data files, zenoss conf files and the events database.
19 '''
20
21 import Globals
22 from ZCmdBase import ZCmdBase
23 import sys
24 import os
25 import os.path
26 from datetime import date
27 import getpass
28 import ConfigParser
29 import time
30 import commands
31 from ZenBackupBase import *
32
33 MAX_UNIQUE_NAME_ATTEMPTS = 1000
34
35
37
38
40 ''' Returns True is zeo appears to be running, false otherwise.
41 '''
42 cmd = '%s/bin/zeoup.py -p 8100' % self.zenhome
43 output = commands.getoutput(cmd)
44 return output.startswith('Elapsed time:')
45
46
48 ''' Return dbname, dbuser, dbpass from saved settings
49 '''
50 zcmd = ZCmdBase(noopts=True)
51 zem = zcmd.dmd.ZenEventManager
52 for key, default, zemAttr in CONFIG_FIELDS:
53 if not getattr(self.options, key, None):
54 setattr(self.options, key,
55 getattr(zem, zemAttr, None) or default)
56
57
72
73
75 def getName(index=0):
76 return 'zenbackup_%s%s.tgz' % (date.today().strftime('%Y%m%d'),
77 (index and '_%s' % index) or '')
78 backupDir = os.path.join(self.zenhome, 'backups')
79 if not os.path.exists(backupDir):
80 os.mkdir(backupDir, 0750)
81 for i in range(MAX_UNIQUE_NAME_ATTEMPTS):
82 name = os.path.join(backupDir, getName(i))
83 if not os.path.exists(name):
84 break
85 else:
86 sys.stderr.write('Can not determine a unique file name to us'
87 ' in the backup directory (%s).' % backupDir +
88 ' Use --outfile to specify location for the backup'
89 ' file.\n')
90 sys.exit(-1)
91 return name
92
93
95 """basic options setup sub classes can add more options here"""
96 ZenBackupBase.buildOptions(self)
97 self.parser.add_option('--dbname',
98 dest='dbname',
99 default=None,
100 help='MySQL events database name.'
101 ' By default this will be fetched from zenoss'
102 ' unless --dont-fetch-args is set.'),
103 self.parser.add_option('--dbuser',
104 dest='dbuser',
105 default=None,
106 help='MySQL username.'
107 ' By default this will be fetched from zenoss'
108 ' unless --dont-fetch-args is set.'),
109 self.parser.add_option('--dbpass',
110 dest='dbpass',
111 default=None,
112 help='MySQL password.'
113 ' By default this will be fetched from zenoss'
114 ' unless --dont-fetch-args is set.'),
115 self.parser.add_option('--dont-fetch-args',
116 dest='fetchArgs',
117 default=True,
118 action='store_false',
119 help='By default dbname, dbuser and dbpass'
120 ' are retrieved from zenoss if not'
121 ' specified and if zenoss is available.'
122 ' This disables fetching of these values'
123 ' from zenoss.')
124 self.parser.add_option('--file',
125 dest="file",
126 default=None,
127 help='File to backup to.'
128 ' Backups will by default be placed'
129 ' in $ZENHOME/backups/')
130 self.parser.add_option('--no-eventsdb',
131 dest="noEventsDb",
132 default=False,
133 action='store_true',
134 help='Do not include the events database'
135 ' in the backup.')
136 self.parser.add_option('--stdout',
137 dest="stdout",
138 default=False,
139 action='store_true',
140 help='Send backup to stdout instead of a file')
141 self.parser.add_option('--save-mysql-access',
142 dest='saveSettings',
143 default=False,
144 action='store_true',
145 help='Include dbname, dbuser and dbpass'
146 ' in backup'
147 ' file for use during restore.')
148
149
151 ''' Create a backup of the data and configuration for a zenoss install.
152 getWhatYouCan == True means to continue without reporting errors even
153 if this appears to be an incomplete zenoss install.
154 '''
155
156
157
158 if self.options.stdout and self.options.verbose:
159 sys.stderr.write('You cannot specify both'
160 ' --stdout and --verbose.\n')
161 sys.exit(-1)
162
163
164 if self.options.fetchArgs and not self.options.noEventsDb:
165 if self.isZeoUp():
166 self.msg('Getting mysql dbname, user, password from zeo')
167 self.readSettingsFromZeo()
168 else:
169 self.msg('Unable to get mysql info from zeo.'
170 ' Looks like zeo is not running.')
171
172 if not self.options.dbname:
173 self.options.dbname = 'events'
174 if not self.options.dbuser:
175 self.options.dbuser = 'zenoss'
176
177
178
179
180 rootTempDir = self.getTempDir()
181 tempDir = os.path.join(rootTempDir, BACKUP_DIR)
182 os.mkdir(tempDir, 0750)
183
184
185 if self.options.saveSettings:
186 self.saveSettings(tempDir)
187
188
189 if self.options.noEventsDb:
190 self.msg('Skipping backup of events database.')
191 else:
192 self.msg('Backup up events database.')
193 cmd = 'mysqldump -u"%s" %s --routines %s > %s' % (
194 self.options.dbuser,
195 self.getPassArg(),
196 self.options.dbname,
197 os.path.join(tempDir, 'events.sql'))
198 if os.system(cmd): return -1
199
200
201 self.msg('Backing up zeo database.')
202 repozoDir = os.path.join(tempDir, 'repozo')
203 os.mkdir(repozoDir, 0750)
204 cmd = ('%s --backup --full ' %
205 self.getRepozoPath() +
206 '--repository %s --file %s/var/Data.fs' %
207 (repozoDir, self.zenhome))
208 if os.system(cmd): return -1
209
210
211 self.msg('Backing up config files.')
212 cmd = 'tar -cf %s --exclude *.zdsock --directory %s %s' % (
213 os.path.join(tempDir, 'etc.tar'),
214 self.zenhome,
215 'etc')
216 if os.system(cmd): return -1
217
218
219 self.msg('Backing up performance data.')
220 cmd = 'tar Ccf %s %s %s' % (
221 self.zenhome,
222 os.path.join(tempDir, 'perf.tar'),
223 'perf')
224 if os.system(cmd): return -1
225
226
227 self.msg('Packaging backup file.')
228 if self.options.file:
229 outfile = self.options.file
230 else:
231 outfile = self.getDefaultBackupFile()
232 tempHead, tempTail = os.path.split(tempDir)
233 cmd = 'tar czfC %s %s %s' % (
234 self.options.stdout and '-' or outfile,
235 tempHead, tempTail)
236 self.msg('Backup file written to %s' % outfile)
237
238 if os.system(cmd): return -1
239
240
241 self.msg('Cleaning up temporary files.')
242 cmd = 'rm -r %s' % rootTempDir
243 if os.system(cmd): return -1
244
245 self.msg('Backup complete.')
246 return 0
247
248
249 if __name__ == '__main__':
250 zb = ZenBackup()
251 if zb.makeBackup():
252 sys.exit(-1)
253