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