|
|
|
@ -49,6 +49,74 @@ tr.setLanguage(sys.modules[__name__])
|
|
|
|
|
|
|
|
|
|
pcs = cl_utils.prettyColumnStr
|
|
|
|
|
|
|
|
|
|
class report():
|
|
|
|
|
"""Класс для выдачи данных в табличном виде"""
|
|
|
|
|
def __init__(self, title, headerList, dataList):
|
|
|
|
|
# Заголовок
|
|
|
|
|
self.title = title
|
|
|
|
|
# Cписок элементов первой строки таблицы
|
|
|
|
|
self.headerList = headerList
|
|
|
|
|
# Список строк (каждая строка - список элементов)
|
|
|
|
|
self.dataList = dataList
|
|
|
|
|
# Список ширин колонок
|
|
|
|
|
self.columnsWidth = self.getColumsnWidth()
|
|
|
|
|
|
|
|
|
|
def getColumsnWidth(self):
|
|
|
|
|
"""Находит максимальную ширину каждой колонки
|
|
|
|
|
|
|
|
|
|
результат список ширин колонок
|
|
|
|
|
"""
|
|
|
|
|
columnsWidth = []
|
|
|
|
|
lenCol = 0
|
|
|
|
|
for s in self.headerList:
|
|
|
|
|
lenCol += 1
|
|
|
|
|
columnsWidth.append(len(cl_utils._toUNICODE(s)))
|
|
|
|
|
maxLenCol = lenCol
|
|
|
|
|
# Вычисляем максимальное количество столбцов
|
|
|
|
|
for s in self.dataList:
|
|
|
|
|
lenS = len(s)
|
|
|
|
|
if maxLenCol < lenS:
|
|
|
|
|
maxLenCol = lenS
|
|
|
|
|
if maxLenCol > lenCol:
|
|
|
|
|
appCol = maxLenCol - lenCol
|
|
|
|
|
# Добавляем элементы в список ширин
|
|
|
|
|
for i in range(appCol):
|
|
|
|
|
columnsWidth.append(0)
|
|
|
|
|
# Вычисляем ширину столбцов
|
|
|
|
|
for e in self.dataList:
|
|
|
|
|
i = 0
|
|
|
|
|
for s in e:
|
|
|
|
|
lenS = len(cl_utils._toUNICODE(s))
|
|
|
|
|
if columnsWidth[i] < lenS:
|
|
|
|
|
columnsWidth[i] = lenS
|
|
|
|
|
i += 1
|
|
|
|
|
return columnsWidth
|
|
|
|
|
|
|
|
|
|
def createFormatStr(self, listStr):
|
|
|
|
|
"""Создает список (текст, ширина ...)"""
|
|
|
|
|
strList = []
|
|
|
|
|
lenStr = len(listStr)
|
|
|
|
|
for i in range(len(self.columnsWidth)):
|
|
|
|
|
if lenStr > i:
|
|
|
|
|
strList.append(listStr[i])
|
|
|
|
|
else:
|
|
|
|
|
strList.append("")
|
|
|
|
|
strList.append(self.columnsWidth[i])
|
|
|
|
|
return strList
|
|
|
|
|
|
|
|
|
|
def printReport(self):
|
|
|
|
|
"""Напечатать данные в табличном виде"""
|
|
|
|
|
print self.title
|
|
|
|
|
listStrSep = []
|
|
|
|
|
for lenCol in self.columnsWidth:
|
|
|
|
|
listStrSep.append("-"*lenCol)
|
|
|
|
|
print cl_utils.columnStr(*self.createFormatStr(listStrSep)),
|
|
|
|
|
print cl_utils.columnStr(*self.createFormatStr(self.headerList)),
|
|
|
|
|
print cl_utils.columnStr(*self.createFormatStr(listStrSep)),
|
|
|
|
|
for s in self.dataList:
|
|
|
|
|
print cl_utils.columnStr(*self.createFormatStr(s)),
|
|
|
|
|
print cl_utils.columnStr(*self.createFormatStr(listStrSep)),
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def adminConnectLdap(fun):
|
|
|
|
|
"""Cоединение с LDAP администратором сервиса (декоратор)
|
|
|
|
@ -5841,7 +5909,7 @@ outdated. If the backup is obsolete, use cl-backup."))
|
|
|
|
|
# другого компьютера
|
|
|
|
|
replServices = []
|
|
|
|
|
if options.has_key("repl"):
|
|
|
|
|
# Находим имена сервисов р<>пликации для этого сервера
|
|
|
|
|
# Находим имена сервисов р<><EFBFBD><EFBFBD>пликации для этого сервера
|
|
|
|
|
# и инициализируем переменные
|
|
|
|
|
replServices = self.getArchReplServices()
|
|
|
|
|
if not replServices:
|
|
|
|
@ -7137,6 +7205,7 @@ class cl_ldap(shareLdap):
|
|
|
|
|
'repldap':11,
|
|
|
|
|
'cl-replication':12,
|
|
|
|
|
'replcron':13,
|
|
|
|
|
'cl-info':14,
|
|
|
|
|
}
|
|
|
|
|
# Cвязь сервисов и действующих опций
|
|
|
|
|
self.relServices = {"samba":[_("Common options"),
|
|
|
|
@ -8060,6 +8129,13 @@ the password will be changed only for Samba account")
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("replication off")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(14,),
|
|
|
|
|
'shortOption':"u",
|
|
|
|
|
'optVal':"CONDITION",
|
|
|
|
|
'longOption':"user",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("users") + " or all"
|
|
|
|
|
},
|
|
|
|
|
#{'progAccess':(0,1,2,4,5,6),
|
|
|
|
|
#'shortOption':"s",
|
|
|
|
|
#'longOption':"set",
|
|
|
|
@ -8080,12 +8156,12 @@ the password will be changed only for Samba account")
|
|
|
|
|
"ldap " + servName, self.consolewidth-self.column_width)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{'progAccess':(0,1,2,3,4,5,6,7,9,12),
|
|
|
|
|
{'progAccess':(0,1,2,3,4,5,6,7,9,12,14),
|
|
|
|
|
'helpChapter':_("Services"),
|
|
|
|
|
'help':pcs(" unix", self.column_width,
|
|
|
|
|
"unix " + servName, self.consolewidth-self.column_width)
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(3,4,5,6,7,9,12),
|
|
|
|
|
{'progAccess':(3,4,5,6,7,9,12,14),
|
|
|
|
|
'helpChapter':_("Services"),
|
|
|
|
|
'help':pcs(" samba", self.column_width,
|
|
|
|
|
"samba " + servName, self.consolewidth-self.column_width)
|
|
|
|
@ -8096,17 +8172,17 @@ the password will be changed only for Samba account")
|
|
|
|
|
_("using unix group"),
|
|
|
|
|
self.consolewidth-self.column_width)
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(0,1,2,3,4,5,6,7,9,12),
|
|
|
|
|
{'progAccess':(0,1,2,3,4,5,6,7,9,12,14),
|
|
|
|
|
'helpChapter':_("Services"),
|
|
|
|
|
'help':pcs(" mail", self.column_width,
|
|
|
|
|
"mail " + servName, self.consolewidth-self.column_width)
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(0,1,2,3,4,5,6,7,9),
|
|
|
|
|
{'progAccess':(0,1,2,3,4,5,6,7,9,14),
|
|
|
|
|
'helpChapter':_("Services"),
|
|
|
|
|
'help':pcs(" jabber", self.column_width,
|
|
|
|
|
"jabber " + servName, self.consolewidth-self.column_width)
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(3,4,5,6,7,9),
|
|
|
|
|
{'progAccess':(3,4,5,6,7,9,14),
|
|
|
|
|
'helpChapter':_("Services"),
|
|
|
|
|
'help':pcs(" ftp", self.column_width,
|
|
|
|
|
"ftp " + servName, self.consolewidth-self.column_width)
|
|
|
|
@ -10314,6 +10390,166 @@ together with option '-r'") + " ...")
|
|
|
|
|
self.printOK(_("Replication setuped") + " ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
class cl_info(cl_utils2.cl_smartcon):
|
|
|
|
|
"""Класс для вывода информации"""
|
|
|
|
|
def getInfoServer(self, options, service):
|
|
|
|
|
"""Выводит на печать информацию"""
|
|
|
|
|
if options.has_key("u"):
|
|
|
|
|
userOpt = options['u']
|
|
|
|
|
users = []
|
|
|
|
|
if userOpt == "all":
|
|
|
|
|
headerList , users = self.getAllUsers(service)
|
|
|
|
|
title=_("All users in LDAP for service %s")%service.capitalize()
|
|
|
|
|
dataList = users
|
|
|
|
|
#dataList = map(lambda x: type(x) != types.ListType and [x],
|
|
|
|
|
#users)
|
|
|
|
|
repObj = report(title, headerList, dataList)
|
|
|
|
|
repObj.printReport()
|
|
|
|
|
#print users
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def getQueryLDAP(self, service, branch, searchAttr, searchStr,
|
|
|
|
|
retrAttrs=None):
|
|
|
|
|
"""Выдает данные из LDAP"""
|
|
|
|
|
branchData = {'users':'relUsersDN',
|
|
|
|
|
'groups':'relGroupsDN',
|
|
|
|
|
'computers':'relComputersDN'}
|
|
|
|
|
if not branchData.has_key(branch):
|
|
|
|
|
self.printERROR(_("getQueryLDAP service=%s")%service)
|
|
|
|
|
self.printERROR(_("ERROR: getQueryLDAP incorrect branch=%s")%branch)
|
|
|
|
|
return False
|
|
|
|
|
relAttr = branchData[branch]
|
|
|
|
|
try:
|
|
|
|
|
exec ("servObj=serv%s()" %service.capitalize())
|
|
|
|
|
except:
|
|
|
|
|
self.printERROR(\
|
|
|
|
|
_("ERROR: getQueryLDAP incorrect service=%s")%service)
|
|
|
|
|
return False
|
|
|
|
|
if not servObj.__dict__.has_key(relAttr):
|
|
|
|
|
self.printERROR(_("getQueryLDAP service=%s")%service)
|
|
|
|
|
self.printERROR(_("ERROR: getQueryLDAP incorrect branch=%s")%branch)
|
|
|
|
|
return False
|
|
|
|
|
searchRes = servObj.searchLdapDN(searchStr, getattr(servObj, relAttr),
|
|
|
|
|
searchAttr, retrAttrs)
|
|
|
|
|
return searchRes
|
|
|
|
|
|
|
|
|
|
def getAllUsers(self, service):
|
|
|
|
|
"""Выдает список login-ов всех пользователей сервиса"""
|
|
|
|
|
searchAttr = "uid"
|
|
|
|
|
searchStr = "*"
|
|
|
|
|
if service == "unix":
|
|
|
|
|
data = [("LOGIN","uid"),
|
|
|
|
|
("NAME","cn"),
|
|
|
|
|
("LOCK","shadowExpire"),
|
|
|
|
|
("VISIBLE","shadowFlag"),
|
|
|
|
|
("UID","uidNumber"),
|
|
|
|
|
("GID","gidNumber"),
|
|
|
|
|
("HOME","homeDirectory"),
|
|
|
|
|
("PWD","userPassword"),
|
|
|
|
|
("DATE_PWD","shadowLastChange"),
|
|
|
|
|
("JID","registeredAddress"),
|
|
|
|
|
("MAIL","mail")]
|
|
|
|
|
elif service == "samba":
|
|
|
|
|
data = [("LOGIN","uid"),
|
|
|
|
|
("NAME","displayName"),
|
|
|
|
|
("LOCK","sambaAcctFlags"),
|
|
|
|
|
("PWD","sambaNTPassword"),
|
|
|
|
|
("DATE_PWD","sambaPwdLastSet")]
|
|
|
|
|
headers = map(lambda x: x[0], data)
|
|
|
|
|
retrAttrs = map(lambda x: x[1], data)
|
|
|
|
|
|
|
|
|
|
loginsUsers = []
|
|
|
|
|
searchRes = self.getQueryLDAP(service, "users", searchAttr, searchStr,
|
|
|
|
|
retrAttrs)
|
|
|
|
|
if not searchRes:
|
|
|
|
|
return (headers , [])
|
|
|
|
|
for info in searchRes:
|
|
|
|
|
listAttr = []
|
|
|
|
|
for attr in retrAttrs:
|
|
|
|
|
if attr in info[0][1]:
|
|
|
|
|
ldapValue = info[0][1][attr]
|
|
|
|
|
# Конвертируем время в текстовый формат
|
|
|
|
|
if attr == "shadowLastChange" or\
|
|
|
|
|
attr == "sambaPwdLastSet":
|
|
|
|
|
ldapValue[0] = self. _convDatatoStr(ldapValue[0])
|
|
|
|
|
# Ставим Y в случае выставленного флага
|
|
|
|
|
if attr == "shadowExpire":
|
|
|
|
|
if ldapValue[0] == "1":
|
|
|
|
|
ldapValue[0] = "Y"
|
|
|
|
|
else:
|
|
|
|
|
ldapValue[0] = "N"
|
|
|
|
|
if attr == "sambaAcctFlags":
|
|
|
|
|
if ldapValue[0] == "[DU ]":
|
|
|
|
|
ldapValue[0] = "Y"
|
|
|
|
|
else:
|
|
|
|
|
ldapValue[0] = "N"
|
|
|
|
|
if attr == "userPassword":
|
|
|
|
|
if ldapValue[0] == "crypt{xxx}":
|
|
|
|
|
ldapValue[0] = "N"
|
|
|
|
|
else:
|
|
|
|
|
ldapValue[0] = "Y"
|
|
|
|
|
if attr == "shadowFlag":
|
|
|
|
|
if ldapValue[0] == "1":
|
|
|
|
|
ldapValue[0] = "Y"
|
|
|
|
|
else:
|
|
|
|
|
ldapValue[0] = "N"
|
|
|
|
|
if attr == "sambaNTPassword":
|
|
|
|
|
ldapValue[0] = "Y"
|
|
|
|
|
|
|
|
|
|
#Если несколько значений то разделяем их запятыми
|
|
|
|
|
value = reduce(lambda x,y: ",".join([x,y])[0] == "," and\
|
|
|
|
|
",".join([x,y])[1:] or ",".join([x,y])[1:]\
|
|
|
|
|
and ",".join([x,y]) , ldapValue, "")
|
|
|
|
|
listAttr.append(value)
|
|
|
|
|
else:
|
|
|
|
|
listAttr.append("N")
|
|
|
|
|
loginsUsers.append(listAttr)
|
|
|
|
|
return (headers, loginsUsers)
|
|
|
|
|
|
|
|
|
|
def _convDatatoStr(self, dataDays):
|
|
|
|
|
"""Конвертирует количество дней с 1970 в строку даты"""
|
|
|
|
|
if dataDays:
|
|
|
|
|
if len(str(dataDays)) <= 6:
|
|
|
|
|
value = long(dataDays)*86400
|
|
|
|
|
elif len(str(dataDays)) > 6:
|
|
|
|
|
value = long(dataDays)
|
|
|
|
|
return reduce(lambda x,y: y+"."+x,map(lambda x: (len(str(x))==1 and\
|
|
|
|
|
"0"+str(x)) or str(x), time.localtime(value)[:3]))
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
def getLockUsers(self, service):
|
|
|
|
|
"""Выдает список login-ов заблокированных пользователей сервиса"""
|
|
|
|
|
searchAttr = ""
|
|
|
|
|
searchStr = ""
|
|
|
|
|
retrAttrs = ["uid"]
|
|
|
|
|
if service == "unix":
|
|
|
|
|
searchAttr = "shadowExpire"
|
|
|
|
|
searchStr = "1"
|
|
|
|
|
elif service == "samba":
|
|
|
|
|
searchAttr = "sambaAcctFlags"
|
|
|
|
|
searchStr = "[DU ]"
|
|
|
|
|
elif service == "mail":
|
|
|
|
|
searchAttr = "accountStatus"
|
|
|
|
|
searchStr = "passive"
|
|
|
|
|
elif service == "jabber":
|
|
|
|
|
searchAttr = "initials"
|
|
|
|
|
searchStr = "No"
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(\
|
|
|
|
|
_("ERROR: getLockUsers incorrect service=%s")%service)
|
|
|
|
|
return False
|
|
|
|
|
if not searchAttr or not searchStr:
|
|
|
|
|
return False
|
|
|
|
|
loginsUsers = []
|
|
|
|
|
searchRes = self.getQueryLDAP(service, "users", searchAttr, searchStr,
|
|
|
|
|
retrAttrs)
|
|
|
|
|
if not searchRes:
|
|
|
|
|
return []
|
|
|
|
|
for info in searchRes:
|
|
|
|
|
loginsUsers.append(info[0][1]['uid'][0])
|
|
|
|
|
return loginsUsers
|
|
|
|
|
|
|
|
|
|
class tsOpt(cl_base.opt):
|
|
|
|
|
"""Класс для обработки параметров и вывода help
|
|
|
|
|
|
|
|
|
|