## Copyright (C) 2001-2005 Red Hat, Inc.
## Copyright (C) 2001, 2002 Than Ngo
## Copyright (C) 2001-2005 Harald Hoyer
## Copyright (C) 2001, 2002 Philipp Knirsch
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os.path
from netconfpkg import NCDeviceList, NCIPsecList
from netconfpkg.NCDeviceList import ConfDevices
from netconfpkg.NCProfile import Profile
from netconfpkg.NC_functions import (_, log, SYSCONFNETWORK,
getRoot, updateNetworkScripts,
SYSCONFPROFILEDIR, OLDSYSCONFDEVICEDIR,
RESOLVCONF, HOSTSCONF, TestError,
SYSCONFDEVICEDIR, mkdir, issamefile,
unlink, link, rename, rmdir,
getTestEnv, generic_error_dialog,
generic_yesno_dialog, RESPONSE_YES)
from netconfpkg.conf import ConfShellVar, ConfEResolv
from netconfpkg.gdt import Gdtlist, gdtlist_properties
class ProfileList_base(Gdtlist):
gdtlist_properties(Profile)
class MyFileList(list):
def __setitem__(self, key, value):
value = os.path.abspath(value)
log.log(5, "MyFileList.__setitem__(self, %s, %s)" % (str(key),
str(value)))
return list.__setitem__(self, key, value)
def __contains__(self, obj):
obj = os.path.abspath(obj)
ret = list.__contains__(self, os.path.abspath(obj))
log.log(5, "MyFileList.__contains__(self, %s) == %s"
% (str(obj), str(ret)))
return ret
def append(self, obj):
obj = os.path.abspath(obj)
log.log(5, "MyFileList.append(self, %s)" % str(obj))
return list.append(self, os.path.abspath(obj))
class ProfileList(ProfileList_base):
def __init__(self):
super(ProfileList, self).__init__()
self.error = None
def load(self):
# pylint: disable-msg=W0201
self.curr_prof = 'default'
nwconf = ConfShellVar.ConfShellVar(getRoot() + SYSCONFNETWORK)
if nwconf.has_key('CURRENT_PROFILE'):
self.curr_prof = nwconf['CURRENT_PROFILE']
if nwconf.has_key('HOSTNAME'):
self.use_hostname = nwconf['HOSTNAME']
else:
self.use_hostname = 'localhost'
if self.curr_prof == None or self.curr_prof == '':
self.curr_prof = 'default'
updateNetworkScripts()
self.__delslice__(0, len(self))
proflist = []
if os.path.isdir(getRoot() + SYSCONFPROFILEDIR):
proflist = os.listdir(getRoot() + SYSCONFPROFILEDIR)
if proflist:
for pr in proflist:
# 60016
profdir = getRoot() + SYSCONFPROFILEDIR + '/' + pr
if not os.path.isdir(profdir):
continue
self.loadprof(pr, profdir)
else:
self.loadprof('default', None)
else:
self.loadprof('default', None)
prof = self.getActiveProfile()
log.log(5, "ActiveProfile: %s" % str(prof))
prof.DNS.Hostname = self.use_hostname
self.commit()
self.setunmodified()
def loadprof(self, pr, profdir):
devicelist = NCDeviceList.getDeviceList()
ipseclist = NCIPsecList.getIPsecList()
prof = Profile()
self.append(prof)
prof.ProfileName = pr
if pr == self.curr_prof:
prof.Active = True
else:
prof.Active = False
devlist = []
if profdir:
devlist = ConfDevices(profdir)
if not devlist:
devlist = ConfDevices(getRoot() + OLDSYSCONFDEVICEDIR)
for dev in devlist:
for d in devicelist:
if d.DeviceId == dev:
#print >> sys.stderr, "Appending ", d.DeviceId, dev
prof.ActiveDevices.append(dev)
break
for ipsec in devlist:
for d in ipseclist:
if d.IPsecId == ipsec:
prof.ActiveIPsecs.append(ipsec)
break
# CHECK: [198898] new backend for /etc/hosts
if profdir:
try:
prof.HostsList.load(filename = profdir + '/hosts')
except ValueError, e:
self.error = e.message
else:
try:
prof.HostsList.load(filename = HOSTSCONF)
except ValueError, e:
self.error = e.message
# FIXME: [183338] use SEARCH not resolv.conf
dnsconf = ConfEResolv.ConfEResolv()
if profdir:
dnsconf.filename = profdir + '/resolv.conf'
else:
dnsconf.filename = getRoot() + RESOLVCONF
dnsconf.read()
prof.DNS.Hostname = self.use_hostname
prof.DNS.Domainname = ''
prof.DNS.PrimaryDNS = ''
prof.DNS.SecondaryDNS = ''
prof.DNS.TertiaryDNS = ''
if profdir:
nwconf = ConfShellVar.ConfShellVar(profdir + '/network')
else:
nwconf = ConfShellVar.ConfShellVar(getRoot() + SYSCONFNETWORK)
if nwconf['HOSTNAME'] != '':
prof.DNS.Hostname = nwconf['HOSTNAME']
if len(dnsconf['domain']) > 0:
prof.DNS.Domainname = dnsconf['domain'][0]
if dnsconf.has_key('nameservers'):
prof.DNS.PrimaryDNS = dnsconf['nameservers'][0]
if len(dnsconf['nameservers']) > 1:
prof.DNS.SecondaryDNS = dnsconf['nameservers'][1]
if len(dnsconf['nameservers']) > 2:
prof.DNS.TertiaryDNS = dnsconf['nameservers'][2]
sl = prof.DNS.SearchList
if dnsconf.has_key('search'):
for ns in dnsconf['search']:
sl.append(ns)
def test(self):
error = None
for prof in self:
try:
prof.HostsList.test()
except ValueError, e:
if not error:
error = "Profile: %s \n%s" % (prof.ProfileName, e.message)
else:
error += e.message
if error:
raise ValueError(error)
#return
# Keep that test for later versions
devmap = {}
devicelist = NCDeviceList.getDeviceList()
for prof in self:
if not prof.Active:
continue
for devId in prof.ActiveDevices:
for dev in devicelist:
if dev.DeviceId == devId:
device = dev
break
else:
continue
if devmap.has_key(device.Device) and \
device.Alias == devmap[device.Device].Alias:
msg = (_('Device %s uses the same Hardware Device '
'"%s" like %s!\n') \
+ _('Please select another Hardware Device or \n'
'activate only one of them.')) % \
(device.DeviceId, device.Device, \
devmap[device.Device].DeviceId)
raise TestError(msg)
devmap[device.Device] = device
break
def fixInterfaces(self):
return
#===============================================================================
# pppnum = 0
# ipppnum = 0
# isdnnum = 0
# devicelist = NCDeviceList.getDeviceList()
# changed = 0
# for prof in self:
# if not prof.Active:
# continue
# for devid in prof.ActiveDevices:
# for dev in devicelist:
# if dev.DeviceId != devid:
# continue
#
# if dev.Type == MODEM or dev.Type == DSL:
# dstr = "ppp"+str(pppnum)
# if dev.Device != dstr:
# dev.Device = dstr
# changed = 1
# pppnum = pppnum + 1
# elif dev.Type == ISDN:
# if dev.Dialup.EncapMode == 'syncppp':
# dstr = "ippp"+str(ipppnum)
# if dstr != dev.Device:
# dev.Device = dstr
# changed = 1
# if dev.Dialup.ChannelBundling == True:
# ipppnum = ipppnum + 1
# dstr = "ippp"+str(ipppnum)
# if dstr != dev.Dialup.SlaveDevice:
# dev.Dialup.SlaveDevice = dstr
# changed = 1
# ipppnum = ipppnum + 1
# else:
# dstr = "isdn"+str(isdnnum)
# if dstr != dev.Device:
# dev.Device = dstr
# changed = 1
# isdnnum = isdnnum + 1
# break
# break
#===============================================================================
def save(self):
# FIXME: [163040] "Exception Occurred" when saving
# fail gracefully, with informing, which file, and why
import socket
# Just to be safe...
os.umask(0022)
# commit the changes
self.commit()
nwconf = ConfShellVar.ConfShellVar(getRoot() + SYSCONFNETWORK)
# FIXME: [183338] use SEARCH not resolv.conf
dnsconf = ConfEResolv.ConfEResolv()
act_prof = self.getActiveProfile()
if(not getTestEnv()
and socket.gethostname() != act_prof.DNS.Hostname):
if os.getuid() == 0:
# FIXME: [169733] Renaming machine prevents
# applications from opening, if the hostname changed,
# set it system wide (#55746)
retval = generic_yesno_dialog(_(
"""You changed the hostname.
Should the hostname be set to the system now?
This may have the effect, that some X applications do not function properly.
You may have to relogin."""))
if retval == RESPONSE_YES:
os.system("hostname %s" % act_prof.DNS.Hostname)
log.log(2, "change hostname to %s" % act_prof.DNS.Hostname)
newip = '127.0.0.1'
try:
newip = socket.gethostbyname(act_prof.DNS.Hostname)
except socket.error:
if self.use_hostname.find(".") != -1:
self.use_hostname = self.use_hostname.split(".")[0]
for host in act_prof.HostsList:
if host.IP == '127.0.0.1' or host.IP == "::1":
host.Hostname = 'localhost.localdomain'
if 'localhost' not in host.AliasList:
host.AliasList.append('localhost')
# append the hostname to 127.0.0.1,
# if it does not contain a domain
if act_prof.DNS.Hostname.find(".") != -1:
newhostname = act_prof.DNS.Hostname.split(".")[0]
else:
newhostname = act_prof.DNS.Hostname
# Replace the old hostname with the new one if it's already in the alias list.
if newhostname in host.AliasList:
pass
elif self.use_hostname in host.AliasList:
idx = host.AliasList.index(self.use_hostname)
host.AliasList[idx] = newhostname
else:
host.AliasList.append(newhostname)
else:
if newip != "127.0.0.1" and newip != "::1":
# We found an IP for the hostname
for host in act_prof.HostsList:
if host.IP == '127.0.0.1' or host.IP == "::1":
# reset localhost
host.Hostname = 'localhost.localdomain'
if 'localhost' not in host.AliasList:
host.AliasList.append('localhost')
if host.IP == newip:
# found entry in /etc/hosts with our IP
# change the entry
host.createAliasList()
try:
hname = socket.gethostbyaddr(newip)
host.Hostname = hname[0]
host.AliasList.extend(hname[1])
except socket.error:
host.Hostname = act_prof.DNS.Hostname
if host.Hostname != act_prof.DNS.Hostname:
host.AliasList.append(act_prof.DNS.Hostname)
if act_prof.DNS.Hostname.find(".") != -1:
hname = act_prof.DNS.Hostname.split(".")[0]
if not hname in host.AliasList:
host.AliasList.append(hname)
#act_prof.HostsList.commit(changed=False)
nwconf['HOSTNAME'] = act_prof.DNS.Hostname
if act_prof.ProfileName != 'default':
nwconf['CURRENT_PROFILE'] = act_prof.ProfileName
else:
del nwconf['CURRENT_PROFILE']
nwconf.write()
if not os.path.isdir(getRoot() + SYSCONFPROFILEDIR):
mkdir(getRoot() + SYSCONFPROFILEDIR)
files_used = MyFileList()
for prof in self:
if not os.path.isdir(getRoot() + SYSCONFPROFILEDIR +
'/' + prof.ProfileName):
mkdir(getRoot() + SYSCONFPROFILEDIR + '/' +
prof.ProfileName)
files_used.append(getRoot() + SYSCONFPROFILEDIR + '/' +
prof.ProfileName)
nwconf = ConfShellVar.ConfShellVar(getRoot() + SYSCONFPROFILEDIR +
'/' + prof.ProfileName + '/network')
# print >> sys.stderr, "Writing Hostname ",
# prof.ProfileName, prof.DNS.Hostname
nwconf['HOSTNAME'] = prof.DNS.Hostname
nwconf.write()
files_used.append(nwconf.filename)
# FIXME: [183338] use SEARCH not resolv.conf
dnsconf.filename = getRoot() + SYSCONFPROFILEDIR + '/' + \
prof.ProfileName + '/resolv.conf'
files_used.append(dnsconf.filename)
dnsconf['domain'] = ''
if prof.DNS.Domainname:
dnsconf['domain'] = [prof.DNS.Domainname]
else:
del dnsconf['domain']
dnsconf['search'] = []
if prof.DNS.SearchList != []:
dnsconf['search'] = prof.DNS.SearchList
else:
del dnsconf['search']
dnsconf['nameservers'] = []
nameservers = []
if prof.DNS.PrimaryDNS:
nameservers.append(prof.DNS.PrimaryDNS)
if prof.DNS.SecondaryDNS:
nameservers.append(prof.DNS.SecondaryDNS)
if prof.DNS.TertiaryDNS:
nameservers.append(prof.DNS.TertiaryDNS)
dnsconf['nameservers'] = nameservers
# CHECK: [198898] new backend for /etc/hosts
filename = getRoot() + \
SYSCONFPROFILEDIR + '/' + \
prof.ProfileName + \
'/hosts'
prof.HostsList.save(filename=filename)
files_used.append(filename)
dnsconf.write()
for devId in prof.ActiveDevices:
for prefix in [ 'ifcfg-', 'route-', 'keys-']:
devfilename = getRoot() + SYSCONFDEVICEDIR + \
prefix + devId
profilename = getRoot() + SYSCONFPROFILEDIR + '/' + \
prof.ProfileName + '/' + prefix + devId
if os.path.isfile(devfilename):
if not issamefile(devfilename, profilename):
unlink(profilename)
link(devfilename, profilename)
files_used.append(devfilename)
files_used.append(profilename)
# unlink old .route files
profilename = getRoot() + SYSCONFPROFILEDIR + '/' + \
prof.ProfileName + '/' + devId + '.route'
unlink(profilename)
if prof.Active == False and prof.ProfileName != 'default':
continue
# Active Profile or default profile
for prefix in [ 'ifcfg-', 'route-', 'keys-' ]:
devfilename = getRoot() + SYSCONFDEVICEDIR + \
'/' + prefix + devId
profilename = getRoot() + OLDSYSCONFDEVICEDIR + \
'/' + prefix + devId
if os.path.isfile(devfilename):
if not issamefile(devfilename, profilename):
unlink(profilename)
link(devfilename, profilename)
files_used.append(profilename)
# unlink old .route files
unlink(getRoot() + OLDSYSCONFDEVICEDIR + \
'/' + devId + '.route')
for devId in prof.ActiveIPsecs:
for prefix in [ 'ifcfg-', 'keys-']:
devfilename = getRoot() + SYSCONFDEVICEDIR + \
prefix + devId
profilename = getRoot() + SYSCONFPROFILEDIR + '/' + \
prof.ProfileName + '/' + prefix + devId
if os.path.isfile(devfilename):
if not issamefile(devfilename, profilename):
unlink(profilename)
link(devfilename, profilename)
files_used.append(devfilename)
files_used.append(profilename)
if prof.Active == False and prof.ProfileName != 'default':
continue
# Active Profile or default profile
for prefix in [ 'ifcfg-', 'keys-' ]:
devfilename = getRoot() + SYSCONFDEVICEDIR + \
'/' + prefix + devId
profilename = getRoot() + OLDSYSCONFDEVICEDIR + \
'/' + prefix + devId
if os.path.isfile(devfilename):
if not issamefile(devfilename, profilename):
unlink(profilename)
link(devfilename, profilename)
files_used.append(profilename)
if prof.Active == False:
continue
# Special actions for the active profile
for (mfile, cfile) in { RESOLVCONF : '/resolv.conf',
HOSTSCONF : '/hosts' }.items():
hostfile = getRoot() + mfile
conffile = getRoot() + SYSCONFPROFILEDIR + '/' + \
prof.ProfileName + cfile
if(os.path.isfile(conffile)
and (not os.path.isfile(hostfile)
or not issamefile(hostfile, conffile))):
rename(hostfile, hostfile + '.bak')
unlink(hostfile)
link(conffile, hostfile)
os.chmod(hostfile, 0644)
# Remove all unused files that are linked in the device directory
devlist = os.listdir(getRoot() + OLDSYSCONFDEVICEDIR)
for dev in devlist:
if dev.split('-')[0] not in [ 'ifcfg', 'route',
'keys' ] or \
(len(dev) > 6 and \
dev[-6:] == '.route') \
or dev == 'ifcfg-lo':
continue
mfile = getRoot() + OLDSYSCONFDEVICEDIR+'/'+dev
if mfile in files_used:
# Do not remove used files
continue
try:
stat = os.stat(mfile)
if stat[3] > 1:
# Check, if it is a device of neat
# in every profile directory
dirlist = os.listdir(getRoot() + SYSCONFPROFILEDIR)
for mdir in dirlist:
dirname = getRoot() + SYSCONFPROFILEDIR + '/' + mdir
if not os.path.isdir(dirname):
continue
filelist = os.listdir(dirname)
for file2 in filelist:
stat2 = os.stat(dirname + '/' + file2)
if os.path.samestat(stat, stat2):
unlink(mfile)
except OSError, e:
generic_error_dialog(
_("Error removing file %(file)s: %(errormsg)")
% { "file" : mfile, "errormsg" : str(e) } )
# Remove all profile directories except default
proflist = os.listdir(getRoot() + SYSCONFPROFILEDIR)
for prof in proflist:
# Remove all files in the profile directory
filelist = os.listdir(getRoot() + SYSCONFPROFILEDIR + prof)
for mfile in filelist:
filename = getRoot() + SYSCONFPROFILEDIR + prof + '/' + \
mfile
if filename in files_used:
# Do not remove used files
log.log(6, "%s not removed" % filename)
continue
unlink(filename)
filename = getRoot() + SYSCONFPROFILEDIR + prof
if not (filename in files_used):
rmdir(filename)
# commit the changes
self.commit()
self.setunmodified()
def activateDevice (self, deviceid, profile, state=None):
profilelist = getProfileList()
for prof in profilelist:
if prof.ProfileName != profile:
continue
if state:
if deviceid not in prof.ActiveDevices:
prof.ActiveDevices.append(deviceid)
else:
if deviceid in prof.ActiveDevices:
del prof.ActiveDevices[prof.ActiveDevices.index(deviceid)]
def activateIpsec (self, ipsecid, profile, state=None):
profilelist = getProfileList()
for prof in profilelist:
if prof.ProfileName != profile:
continue
if state:
if ipsecid not in prof.ActiveIPsecs:
prof.ActiveIPsecs.append(ipsecid)
else:
if ipsecid in prof.ActiveIPsecs:
del prof.ActiveIPsecs[prof.ActiveIPsecs.index(ipsecid)]
def switchToProfile(self, val, dochange = True):
aprof = None
for prof in self:
if (isinstance(val, str) and prof.ProfileName == val) or \
(isinstance(val, Profile) and prof == val) :
break
else:
return None
modl = self.modified()
for prof in self:
mod = prof.modified()
if (isinstance(val, str) and prof.ProfileName == val) or \
(isinstance(val, Profile) and prof == val) :
prof.Active = True
aprof = prof
else:
prof.Active = False
#if not dochange:
# prof.setunmodified(mod)
#if not dochange:
# self.setunmodified(modl)
return aprof
def getActiveProfile(self):
for prof in self:
if not prof.Active:
continue
return prof
if len(self):
self[0].Active = True
return self[0]
def tostr(self, prefix_string = None):
"returns a string in gdt representation"
#print "tostr %s " % prefix_string
if prefix_string == None:
prefix_string = self.__class__.__name__
mstr = ""
for value in self:
if isinstance(value, Profile):
mstr += value.tostr("%s.%s"
% (prefix_string, value.ProfileName))
return mstr
def fromstr(self, vals, value):
# pylint: disable-msg=W0212
if len(vals) <= 1:
return
if vals[0] == "ProfileList":
del vals[0]
else:
return
for profile in self:
if profile.ProfileName == vals[0]:
profile.fromstr(vals[1:], value)
return
prof = Profile()
self.append(prof)
prof.ProfileName = vals[0]
prof.fromstr(vals[1:], value)
__PFList = None
__PFList_root = getRoot()
def getProfileList(refresh=None):
# pylint: disable-msg=W0603
global __PFList
global __PFList_root
if __PFList == None or refresh or \
__PFList_root != getRoot():
__PFList = ProfileList()
__PFList.load()
__PFList_root = getRoot()
return __PFList
__author__ = "Harald Hoyer "