1 | #!/usr/bin/env python
|
---|
2 | # -*- coding: utf-8 -*-
|
---|
3 | #
|
---|
4 |
|
---|
5 | from PyQt4 import QtGui, QtCore
|
---|
6 | from PyQt4.QtCore import *
|
---|
7 | from PyQt4.QtGui import *
|
---|
8 |
|
---|
9 | import socket
|
---|
10 | import string
|
---|
11 | import random
|
---|
12 | import Ui_baseconfigwizard
|
---|
13 |
|
---|
14 |
|
---|
15 | from nosferatu import bacresources, prettynames, auto_types
|
---|
16 |
|
---|
17 |
|
---|
18 |
|
---|
19 | # TODO: move this into base_classes
|
---|
20 |
|
---|
21 |
|
---|
22 | # default values when creating a new resource
|
---|
23 | defaults = {
|
---|
24 | 'catalog' : 'MyCatalog',
|
---|
25 | 'messages': 'Standard',
|
---|
26 | 'type' : 'Backup',
|
---|
27 | 'piddirectory' : ['/var/run',
|
---|
28 | '/opt/bacula/working',
|
---|
29 | '"C:\\\\Program Files\\\\Bacula\\\\working"'],
|
---|
30 | 'workingdirectory' : ['/var/lib/bacula',
|
---|
31 | '/opt/bacula/working',
|
---|
32 | '"C:\\\\Program Files\\\\Bacula\\\\working"'],
|
---|
33 | 'queryfile' : [ '/usr/lib/bacula/query.sql',
|
---|
34 | '"/opt/bacula/scripts/query.sql"'],
|
---|
35 | 'type': auto_types.jobtypes,
|
---|
36 | 'level': auto_types.joblevels,
|
---|
37 |
|
---|
38 | }
|
---|
39 |
|
---|
40 |
|
---|
41 | class baseconfigwizard(QtGui.QWizard, Ui_baseconfigwizard.Ui_Wizard,):
|
---|
42 | '''
|
---|
43 | This wizard will do a base configuration of any bacula resource type.
|
---|
44 | It displays all required items of the given resource and configures them
|
---|
45 | If the configuration is successful, the resource will be given back,
|
---|
46 | else None
|
---|
47 | If the dirconfig is given, available resources are filled into
|
---|
48 | comboboxes (e.g. available filesets, etc)
|
---|
49 | '''
|
---|
50 |
|
---|
51 | def __init__(self, resource, dirconfig = None ,parent = None):
|
---|
52 | super(baseconfigwizard, self).__init__()
|
---|
53 | self.setupUi(self)
|
---|
54 | self.resource = resource
|
---|
55 | self.dirconfig = dirconfig
|
---|
56 |
|
---|
57 | print "got the following resource to configure: %s " % (resource)
|
---|
58 |
|
---|
59 |
|
---|
60 | self.groupBox.setTitle('basic configuration of a "%s" resource.' % (resource.resourcetype))
|
---|
61 | self.groupBox_2.setTitle('please provide the following information for the %s:' % (prettynames.PrettyNames[resource.resourcetype]))
|
---|
62 | introtext = "The following information has to be configured:\n"
|
---|
63 |
|
---|
64 | for item in resource.items:
|
---|
65 | if item.required:
|
---|
66 | introtext += resource.resourcetype + ' ' +item.name + '\n'
|
---|
67 |
|
---|
68 |
|
---|
69 | self.introtextEdit.setText(introtext)
|
---|
70 |
|
---|
71 | row = 0
|
---|
72 | for item in resource.items:
|
---|
73 | if item.required:
|
---|
74 |
|
---|
75 | if self.dirconfig is not None: # fill the defaults with the resource types found in the director config
|
---|
76 | for res in self.dirconfig.validresourcesset:
|
---|
77 | ressources = self.dirconfig.getResourcesListByResType(res)
|
---|
78 | for r in ressources:
|
---|
79 | #print r.items_dict['name'].storage.value
|
---|
80 | if not defaults.has_key(res):
|
---|
81 | defaults[res] = []
|
---|
82 | if type(defaults[res]) is list:
|
---|
83 | if not r.items_dict['name'].storage.value in set(defaults[res]):
|
---|
84 | defaults[res].append(r.items_dict['name'].storage.value)
|
---|
85 |
|
---|
86 |
|
---|
87 | # put the label
|
---|
88 | newlabel = QtGui.QLabel(self.scrollAreaWidgetContents)
|
---|
89 | #labeltext = prettynames.PrettyNames[resource.resourcetype] +' ' + prettynames.PrettyNames[item.name]
|
---|
90 | labeltext = prettynames.PrettyNames[item.name]
|
---|
91 | newlabel.setText(labeltext)
|
---|
92 | self.gridLayout_4.addWidget(newlabel, row, 0, 1, 1)
|
---|
93 |
|
---|
94 | # do we have default value information?
|
---|
95 | if defaults.has_key(item.name):
|
---|
96 | t = type(defaults[item.name])
|
---|
97 | if t is str:
|
---|
98 | newwidget = QtGui.QLineEdit(self.scrollAreaWidgetContents)
|
---|
99 | self.wizardPage2.registerField(item.name + '*', newwidget) # register all fields as "required"
|
---|
100 | newwidget.setText(defaults[item.name]) # set defaults
|
---|
101 |
|
---|
102 | elif t is list:
|
---|
103 | newwidget = QtGui.QComboBox(self.scrollAreaWidgetContents)
|
---|
104 | self.wizardPage2.registerField(item.name + '*', newwidget) # register all fields as "required"
|
---|
105 | newwidget.addItems(defaults[item.name])
|
---|
106 | newwidget.setEditable(True)
|
---|
107 | newwidget.setCurrentIndex(0)
|
---|
108 | #print defaults[item.name]
|
---|
109 |
|
---|
110 | else:
|
---|
111 | newwidget = QtGui.QLineEdit(self.scrollAreaWidgetContents)
|
---|
112 | self.wizardPage2.registerField(item.name + '*', newwidget) # register all fields as "required"
|
---|
113 | #self.wizardPage2.registerField(item.name + '*', newwidget) # register all fields as "required"
|
---|
114 |
|
---|
115 | self.gridLayout_4.addWidget(newwidget, row, 1, 1, 1) # add new widget (lineedit/combobox)
|
---|
116 | #self.wizardPage2.registerField(item.name + '*', newwidget) # register all fields as "required"
|
---|
117 |
|
---|
118 | if item.name == 'address':
|
---|
119 | newButton = QtGui.QPushButton(self.scrollAreaWidgetContents)
|
---|
120 | newButton.setText('check')
|
---|
121 | self.gridLayout_4.addWidget(newButton, row, 2, 1, 1)
|
---|
122 | self.addressLineEdit = newwidget
|
---|
123 | self.connect(newButton,
|
---|
124 | SIGNAL("clicked()"),
|
---|
125 | self.onaddrCheckButtonClicked
|
---|
126 | )
|
---|
127 |
|
---|
128 |
|
---|
129 | elif item.name == 'password':
|
---|
130 | newButton = QtGui.QPushButton(self.scrollAreaWidgetContents)
|
---|
131 | newButton.setText('generate')
|
---|
132 | self.gridLayout_4.addWidget(newButton, row, 2, 1, 1)
|
---|
133 | self.passwordLineEdit = newwidget
|
---|
134 | self.connect(newButton,
|
---|
135 | SIGNAL("clicked()"),
|
---|
136 | self.onpwgenPasswdClicked
|
---|
137 | )
|
---|
138 | row += 1
|
---|
139 |
|
---|
140 |
|
---|
141 |
|
---|
142 |
|
---|
143 |
|
---|
144 | def initializePage(self,pagenumber):
|
---|
145 | if pagenumber == 2:
|
---|
146 | for item in self.resource.items:
|
---|
147 | if item.required:
|
---|
148 | if defaults.has_key(item.name):
|
---|
149 | t = type(defaults[item.name])
|
---|
150 | if t is list:
|
---|
151 | #print "%s:%s" %(item.name, self.field(item.name))
|
---|
152 | idx,x = self.field(item.name).toInt()
|
---|
153 | #print item.name , self.field(item.name).toInt()
|
---|
154 | item.setValue(defaults[item.name][idx])
|
---|
155 | elif t is str:
|
---|
156 | item.setValue(str(self.field(item.name).toString()))
|
---|
157 | else:
|
---|
158 | #print item.name, self.field(item.name).toString()
|
---|
159 | item.setValue(str(self.field(item.name).toString()))
|
---|
160 |
|
---|
161 | self.previewtextEdit.setText(str(self.resource))
|
---|
162 |
|
---|
163 |
|
---|
164 |
|
---|
165 |
|
---|
166 | def onpwgenPasswdClicked(self):
|
---|
167 | self.passwordLineEdit.setText(bacresources.genPw(None,32))
|
---|
168 |
|
---|
169 | def onaddrCheckButtonClicked(self):
|
---|
170 | hostname = str(self.addressLineEdit.text())
|
---|
171 | ip = self.check_hostname(hostname)
|
---|
172 | if ip != None:
|
---|
173 | reply = QMessageBox.information(self,
|
---|
174 | "hostname OK",
|
---|
175 | "check successful: \n\n \"%s\" \n is at\n %s" % (hostname, ip) ,
|
---|
176 | QMessageBox.Ok)
|
---|
177 | else:
|
---|
178 | reply = QMessageBox.warning(self,
|
---|
179 | "hostname ERROR",
|
---|
180 | "\"%s\" can NOT be resolved!" % (hostname) ,
|
---|
181 | QMessageBox.Ok)
|
---|
182 |
|
---|
183 |
|
---|
184 | def check_hostname(self,hostname):
|
---|
185 | '''
|
---|
186 | try to resolve the given hostname
|
---|
187 | returns the IP or NONE if not resolvable
|
---|
188 | '''
|
---|
189 | if len(hostname) == 0:
|
---|
190 | return None
|
---|
191 | try:
|
---|
192 | ip = socket.gethostbyname(hostname)
|
---|
193 | return ip
|
---|
194 | except:
|
---|
195 | return None
|
---|
196 |
|
---|
197 |
|
---|
198 |
|
---|
199 |
|
---|
200 |
|
---|
201 |
|
---|
202 |
|
---|
203 | if __name__ == "__main__":
|
---|
204 | import sys
|
---|
205 | #def main():
|
---|
206 | print "started"
|
---|
207 | app = QtGui.QApplication(sys.argv)
|
---|
208 | app.setOrganizationDomain("dass-it.de")
|
---|
209 | app.setOrganizationName("dassIT GmbH")
|
---|
210 | app.setApplicationName("dassModus")
|
---|
211 | app.setWindowIcon(QIcon(":/icons/dassit_logo.png"))
|
---|
212 |
|
---|
213 |
|
---|
214 | # create a bacula director configuration
|
---|
215 | dirconf = bacresources.DirectorConfig('')
|
---|
216 | dirstring = '''
|
---|
217 | Director {
|
---|
218 | Name = gonzo-dir
|
---|
219 | Messages = Daemon
|
---|
220 | Password = "0DntXXl7DVkNYYRApYdhKKoy2Huq1CVHwIRAKUwgNA86"
|
---|
221 | Pid Directory = "/var/run"
|
---|
222 | Query File = "/usr/lib/bacula/query.sql"
|
---|
223 | VerID = " | configuration file created on :Thu Jun 17 16:30:45 2010"
|
---|
224 | Working Directory = "/var/lib/bacula"
|
---|
225 | }
|
---|
226 | JobDefs {
|
---|
227 | Name = "DefaultJob"
|
---|
228 | Client = gonzo-fd
|
---|
229 | Fileset = "Full Set"
|
---|
230 | Level = Incremental
|
---|
231 | Messages = Standard
|
---|
232 | Pool = Default
|
---|
233 | Schedule = "WeeklyCycle"
|
---|
234 | Storage = FileStorage
|
---|
235 | Type = Backup
|
---|
236 | }
|
---|
237 | Job {
|
---|
238 | Name = "BackupClient1"
|
---|
239 | JobDefs = "DefaultJob"
|
---|
240 | Write Bootstrap = "/var/lib/bacula/Client1.bsr"
|
---|
241 | }
|
---|
242 | Job {
|
---|
243 | Name = "BackupCatalog"
|
---|
244 | Fileset = "Catalog"
|
---|
245 | JobDefs = "DefaultJob"
|
---|
246 | Level = Full
|
---|
247 | Priority = 11
|
---|
248 | Run After Job = "/usr/lib/bacula/delete_catalog_backup"
|
---|
249 | Run Before Job = "/usr/lib/bacula/make_catalog_backup bacula bacula"
|
---|
250 | Schedule = "WeeklyCycleAfterBackup"
|
---|
251 | Write Bootstrap = "/var/lib/bacula/BackupCatalog.bsr"
|
---|
252 | }
|
---|
253 | Fileset {
|
---|
254 | Name = "Full Set"
|
---|
255 | Include {
|
---|
256 | File = /usr/sbin
|
---|
257 | Options {
|
---|
258 | Signature = MD5
|
---|
259 | }
|
---|
260 | }
|
---|
261 | Exclude {
|
---|
262 | File = /var/lib/bacula
|
---|
263 | File = /tmp
|
---|
264 | File = /proc
|
---|
265 | File = /tmp
|
---|
266 | File = /.journal
|
---|
267 | File = /.fsck
|
---|
268 | }
|
---|
269 | }
|
---|
270 |
|
---|
271 | Fileset {
|
---|
272 | Name = "Full Set2"
|
---|
273 | Include {
|
---|
274 | File = /usr/sbin
|
---|
275 | Options {
|
---|
276 | Signature = MD5
|
---|
277 | }
|
---|
278 | }
|
---|
279 | Exclude {
|
---|
280 | File = /var/lib/bacula
|
---|
281 | File = /tmp
|
---|
282 | File = /proc
|
---|
283 | File = /tmp
|
---|
284 | File = /.journal
|
---|
285 | File = /.fsck
|
---|
286 | }
|
---|
287 | }
|
---|
288 |
|
---|
289 |
|
---|
290 | Schedule {
|
---|
291 | Name = "WeeklyCycle"
|
---|
292 | Run = Full 1st sun at 23:05
|
---|
293 | Run = Differential 2nd-5th sun at 23:05
|
---|
294 | Run = Incremental mon-sat at 23:05
|
---|
295 | }
|
---|
296 | Client {
|
---|
297 | Name = gonzo-fd
|
---|
298 | Address = localhost
|
---|
299 | Catalog = MyCatalog
|
---|
300 | File Retention = 30 days
|
---|
301 | Job Retention = 6 months
|
---|
302 | Password = "H/cjI5EOGYbiQ1jWb+1DSxQZc8VKncvt9GOuyDKQvE5E"
|
---|
303 | }
|
---|
304 | Client {
|
---|
305 | Name = second-client-fd
|
---|
306 | Address = localhost
|
---|
307 | Catalog = MyCatalog
|
---|
308 | File Retention = 30 days
|
---|
309 | Job Retention = 6 months
|
---|
310 | Password = "H/cjI5EOGYbiQ1jWb+1DSxQZc8VKncvt9GOuyDKQvE5E"
|
---|
311 | }
|
---|
312 |
|
---|
313 |
|
---|
314 | Storage {
|
---|
315 | Name = FileStorage
|
---|
316 | Address = localhost
|
---|
317 | Device = FileStorage
|
---|
318 | Media Type = FileStorage
|
---|
319 | Password = "/IUTExp+79Y0ipxZ5cZDq26Pp1Vcq5xI0bszHyTa4+TX"
|
---|
320 | }
|
---|
321 | Messages {
|
---|
322 | Name = Standard
|
---|
323 | Append = "/var/lib/bacula/log" = all, !skipped
|
---|
324 | Catalog = all
|
---|
325 | Console = all, !skipped, !saved
|
---|
326 | Mail = root@localhost = all, !skipped
|
---|
327 | Mail Command = "/usr/sbin/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula: %t %e of %c %l\" %r"
|
---|
328 | Operator = root@localhost = mount
|
---|
329 | Operator Command = "/usr/sbin/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula: Intervention needed for %j\" %r"
|
---|
330 | }
|
---|
331 |
|
---|
332 | Pool {
|
---|
333 | Name = Default
|
---|
334 | Pool Type = Backup
|
---|
335 | Volume Retention = 365 days
|
---|
336 | }
|
---|
337 | Pool {
|
---|
338 | Name = Scratch
|
---|
339 | Pool Type = Backup
|
---|
340 | }
|
---|
341 |
|
---|
342 | '''
|
---|
343 | refdirconfig = bacresources.DirectorConfig(dirstring)
|
---|
344 |
|
---|
345 | for res in dirconf.resources:
|
---|
346 | #print res.items_dict['name']
|
---|
347 | print res.resourcetype
|
---|
348 | if res.resourcetype == "client":
|
---|
349 | r = res
|
---|
350 |
|
---|
351 |
|
---|
352 | wizard = baseconfigwizard(r,refdirconfig)
|
---|
353 | if wizard.exec_():
|
---|
354 | newresource = wizard.resource
|
---|
355 | print newresource
|
---|
356 | else:
|
---|
357 | print "no"
|
---|
358 | #wizard.show()
|
---|
359 |
|
---|
360 |
|
---|
361 | sys.exit(app.exec_())
|
---|
362 |
|
---|
363 |
|
---|