1
2
3
4
5
6
7
8 """
9 This module includes the Config and Up2date Config classes use by the
10 up2date agent to hold config info.
11 """
12
13 import os
14 import sys
15 import locale
16 from rhn.connections import idn_ascii_to_puny, idn_puny_to_unicode
17 from rhn.i18n import ustr, sstr
18
19 try:
20 from urlparse import urlsplit, urlunsplit
21 except ImportError:
22 from urllib.parse import urlsplit, urlunsplit
23
24 import gettext
25 t = gettext.translation('rhn-client-tools', fallback=True)
26
27 if not hasattr(t, 'ugettext'):
28 t.ugettext = t.gettext
29 _ = t.ugettext
30
31
32
33 Defaults = {
34 'enableProxy' : ("Use a HTTP Proxy",
35 0),
36 'serverURL' : ("Remote server URL",
37 "https://your.server.url.here/XMLRPC"),
38 'debug' : ("Whether or not debugging is enabled",
39 0),
40 'systemIdPath' : ("Location of system id",
41 "/etc/sysconfig/rhn/systemid"),
42 'versionOverride' : ("Override the automatically determined "\
43 "system version",
44 ""),
45 'httpProxy' : ("HTTP proxy in host:port format, e.g. "\
46 "squid.example.com:3128",
47 ""),
48 'proxyUser' : ("The username for an authenticated proxy",
49 ""),
50 'proxyPassword' : ("The password to use for an authenticated proxy",
51 ""),
52 'enableProxyAuth' : ("To use an authenticated proxy or not",
53 0),
54 'networkRetries' : ("Number of attempts to make at network "\
55 "connections before giving up",
56 1),
57 'sslCACert' : ("The CA cert used to verify the ssl server",
58 "/usr/share/rhn/RHN-ORG-TRUSTED-SSL-CERT"),
59 'noReboot' : ("Disable the reboot action",
60 0),
61 'disallowConfChanges': ("Config options that can not be overwritten by a config update action",
62 ['sslCACert','serverURL','disallowConfChanges',
63 'noReboot']),
64 }
65
66 FileOptions = ['systemIdPath', 'sslCACert', 'tmpDir', ]
67
68
70 "class for handling persistent config options for the client"
72 self.dict = {}
73 self.fileName = filename
74 if self.fileName:
75 self.load()
76
77 - def load(self, filename = None):
78 if filename:
79 self.fileName = filename
80 if self.fileName == None:
81 return
82 if not os.access(self.fileName, os.R_OK):
83
84 return
85
86 f = open(self.fileName, "r")
87
88 multiline = ''
89 for line in f.readlines():
90
91 if line.find('#') == 0:
92 continue
93 line = multiline + line.strip()
94 if not line:
95 continue
96
97
98 if line[-1] == '\\':
99 multiline = line[:-1].strip()
100 continue
101 else:
102 multiline = ''
103
104 split = line.split('=', 1)
105 if len(split) != 2:
106
107
108 continue
109 key = split[0].strip()
110 value = ustr(split[1].strip())
111
112
113 comment = None
114 pos = key.find("[comment]")
115 if pos != -1:
116 key = key[:pos]
117 comment = value
118 value = None
119
120
121 if value:
122
123 values = value.split(";")
124 if key in ['proxyUser', 'proxyPassword']:
125 value = sstr(value.encode(locale.getpreferredencoding()))
126 elif len(values) == 1:
127 try:
128 value = int(value)
129 except ValueError:
130 pass
131 elif values[0] == "":
132 value = []
133 else:
134
135
136 value = [val.strip() for val in values if val.strip() ]
137
138
139 newval = (comment, value)
140 if key in self.dict:
141 newval = self.dict[key]
142 if comment is not None:
143 newval = (comment, newval[1])
144 if value is not None:
145 newval = (newval[0], value)
146 self.dict[key] = newval
147 f.close()
148
150 if self.fileName == None:
151 return
152
153
154
155
156
157
158
159
160 if not os.access(self.fileName, os.R_OK):
161 if not os.access(os.path.dirname(self.fileName), os.R_OK):
162 print(_("%s was not found" % os.path.dirname(self.fileName)))
163 return
164
165 f = open(self.fileName+'.new', "w")
166 os.chmod(self.fileName+'.new', int('0644', 8))
167
168 f.write("# Automatically generated Red Hat Update Agent "\
169 "config file, do not edit.\n")
170 f.write("# Format: 1.0\n")
171 f.write("")
172 for key in self.dict.keys():
173 (comment, value) = self.dict[key]
174 f.write(sstr(u"%s[comment]=%s\n" % (key, comment)))
175 if type(value) != type([]):
176 value = [ value ]
177 if key in FileOptions:
178 value = map(os.path.abspath, value)
179 f.write(sstr(u"%s=%s\n" % (key, ';'.join(map(str, value)))))
180 f.write("\n")
181 f.close()
182 os.rename(self.fileName+'.new', self.fileName)
183
184
187
189
190 return name in self
191
194
197
200
201
202
207
209 if name in self.dict:
210 val = self.dict[name]
211 else:
212 val = (None, None)
213 self.dict[name] = (val[0], value)
214
215
216 - def info(self, name):
220
221
222
223
231
232
233
235 if name in self.runtime:
236 return True
237 if name in self.stored:
238 return True
239 return False
240
242
243 return name in self
244
246 ret = list(self.runtime.keys())
247 for k in self.stored.keys():
248 if k not in ret:
249 ret.append(k)
250 return ret
251
257
263
265 return len(self.keys())
266
268 self.runtime[name] = value
269
270
272 if name in self.runtime:
273 return self.runtime[name]
274 if name in self.stored:
275 return self.stored[name]
276 return None
277
278
279
280 - def info(self, name):
281 return self.stored.info(name)
282
285
286 - def load(self, filename):
287 self.stored.load(filename)
288
289 for k in self.stored.keys():
290 if not k in self.runtime:
291 continue
292
293 del self.runtime[k]
294
295
296 - def set(self, name, value):
297 self.stored[name] = value
298
299 if name in self.runtime:
300 del self.runtime[name]
301
302
304 """ returns proxy string in format hostname:port
305 hostname is converted to Punycode (RFC3492) if needed
306 """
307 cfg = initUp2dateConfig()
308 proxy = None
309 proxyHost = cfg["httpProxy"]
310
311 if proxyHost:
312 if proxyHost[:7] == "http://":
313 proxyHost = proxyHost[7:]
314 parts = proxyHost.split(':')
315 parts[0] = str(idn_ascii_to_puny(parts[0]))
316 proxy = ':'.join(parts)
317
318 return proxy
319
321 """ returns url where hostname is converted to Punycode (RFC3492) """
322 s = urlsplit(url)
323 return sstr(urlunsplit((s[0], ustr(idn_ascii_to_puny(s[1])), s[2], s[3], s[4])))
324
326 """ returns url where hostname is converted from Punycode (RFC3492). Returns unicode string. """
327 s = urlsplit(url)
328 return ustr(urlunsplit((s[0], idn_puny_to_unicode(s[1]), s[2], s[3], s[4])))
329
331 """ return list of serverURL from config
332 Note: in config may be one value or more values, but this
333 function always return list
334 """
335 cfg = initUp2dateConfig()
336
337
338 if type(cfg['serverURL']) == type([]):
339 return [convert_url_to_puny(i) for i in cfg['serverURL']]
340 else:
341 return [convert_url_to_puny(cfg['serverURL'])]
342
347
352
353
355 """This function is the right way to get at the up2date config."""
356 global cfg
357 try:
358 cfg
359 except NameError:
360 cfg = None
361
362 if cfg == None:
363 cfg = Config(cfg_file)
364 cfg["isatty"] = False
365 if sys.stdout.isatty():
366 cfg["isatty"] = True
367
368 return cfg
369