Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624378
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
27 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/shell/modules/completion.py b/shell/modules/completion.py
index 67a69109e1..c8b13371ba 100644
--- a/shell/modules/completion.py
+++ b/shell/modules/completion.py
@@ -1,490 +1,478 @@
# Copyright (C) 2008 Dejan Muhamedagic <dmuhamedagic@suse.de>
#
# 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 software 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 library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
import os
import time
import copy
import readline
from cibconfig import CibFactory
from cibstatus import CibStatus
from levels import Levels
from ra import *
from vars import Vars
from utils import *
from xmlutil import *
class CompletionHelp(object):
'''
Print some help on whatever last word in the line.
'''
timeout = 60 # don't print again and again
def __init__(self):
self.laststamp = 0
self.lastitem = ''
def help(self,f,*args):
words = readline.get_line_buffer().split()
if not words:
return
key = words[-1]
if key.endswith('='):
key = key[0:-1]
if self.lastitem == key and \
time.time() - self.laststamp < self.timeout:
return
help_s = f(key,*args)
if help_s:
print "\n%s" % help_s
print "%s%s" % (vars.prompt,readline.get_line_buffer()),
self.laststamp = time.time()
self.lastitem = key
def attr_cmds(idx,delimiter = False):
if delimiter:
return ' '
return ["delete","set","show"]
def nodes_list(idx,delimiter = False):
if delimiter:
return ' '
return listnodes()
def shadows_list(idx,delimiter = False):
if delimiter:
return ' '
return listshadows()
-def listtemplates():
- l = []
- for f in os.listdir(vars.tmpl_dir):
- if os.path.isfile("%s/%s" % (vars.tmpl_dir,f)):
- l.append(f)
- return l
-def listconfigs():
- l = []
- for f in os.listdir(vars.tmpl_conf_dir):
- if os.path.isfile("%s/%s" % (vars.tmpl_conf_dir,f)):
- l.append(f)
- return l
def templates_list(idx,delimiter = False):
if delimiter:
return ' '
return listtemplates()
def config_list(idx,delimiter = False):
if delimiter:
return ' '
return listconfigs()
def config_list_method(idx,delimiter = False):
if delimiter:
return ' '
return listconfigs() + ["replace","update"]
def shadows_live_list(idx,delimiter = False):
if delimiter:
return ' '
return listshadows() + ['live']
def rsc_list(idx,delimiter = False):
if delimiter:
return ' '
doc = resources_xml()
if not doc:
return []
nodes = get_interesting_nodes(doc,[])
return [x.getAttribute("id") for x in nodes if is_resource(x)]
def null_list(idx,delimiter = False):
if delimiter:
return ' '
return []
def loop(idx,delimiter = False):
"just a marker in a list"
pass
def id_xml_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_factory.id_list() + ['xml','changed']
def id_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_factory.id_list()
def f_prim_id_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_factory.f_prim_id_list()
def f_children_id_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_factory.f_children_id_list()
def rsc_id_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_factory.rsc_id_list()
def node_id_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_factory.node_id_list()
def node_attr_keyw_list(idx,delimiter = False):
if delimiter:
return ' '
return vars.node_attributes_keyw
def status_node_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_status.status_node_list()
def status_rsc_list(idx,delimiter = False):
if delimiter:
return ' '
return cib_status.status_rsc_list()
def node_states_list(idx,delimiter = False):
if delimiter:
return ' '
return vars.node_states
def ra_operations_list(idx,delimiter = False):
if delimiter:
return ' '
return vars.ra_operations
def lrm_exit_codes_list(idx,delimiter = False):
if delimiter:
return ' '
return vars.lrm_exit_codes.keys()
def lrm_status_codes_list(idx,delimiter = False):
if delimiter:
return ' '
return vars.lrm_status_codes.keys()
def skills_list(idx,delimiter = False):
if delimiter:
return ' '
return user_prefs.skill_levels.keys()
def ra_classes_list(idx,delimiter = False):
if delimiter:
return ':'
return ra_classes()
#
# completion for primitives including help for parameters
# (help also available for properties)
#
def get_primitive_type(words):
try:
idx = words.index("primitive") + 2
type_word = words[idx]
except: type_word = ''
return type_word
def ra_type_list(toks,idx,delimiter):
if idx == 2:
if toks[0] == "ocf":
dchar = ':'
l = ra_providers_all()
else:
dchar = ' '
l = ra_types(toks[0])
elif idx == 3:
dchar = ' '
if toks[0] == "ocf":
l = ra_types(toks[0],toks[1])
else:
l = ra_types(toks[0])
if delimiter:
return dchar
return l
def prim_meta_attr_list(idx,delimiter = False):
if delimiter:
return '='
return vars.rsc_meta_attributes
def op_attr_list(idx,delimiter = False):
if delimiter:
return '='
return vars.op_attributes
def operations_list():
return vars.op_cli_names
def prim_complete_meta(ra,delimiter = False):
if delimiter:
return '='
return prim_meta_attr_list(0,delimiter)
def prim_complete_op(ra,delimiter):
words = split_buffer()
if (readline.get_line_buffer()[-1] == ' ' and words[-1] == "op") \
or (readline.get_line_buffer()[-1] != ' ' and words[-2] == "op"):
dchar = ' '
l = operations_list()
else:
if readline.get_line_buffer()[-1] == '=':
dchar = ' '
l = []
else:
dchar = '='
l = op_attr_list()
if delimiter:
return dchar
return l
def prim_complete_params(ra,delimiter):
if readline.get_line_buffer()[-1] == '=':
dchar = ' '
l = []
else:
dchar = '='
l = ra.completion_params()
if delimiter:
return dchar
return l
def prim_params_info(key,ra):
return ra.meta_parameter(key)
def meta_attr_info(key,ra):
pass
def op_attr_info(key,ra):
pass
def get_lastkeyw(words,keyw):
revwords = copy.copy(words)
revwords.reverse()
for w in revwords:
if w in keyw:
return w
def primitive_complete_complex(idx,delimiter = False):
'''
This completer depends on the content of the line, i.e. on
previous tokens, in particular on the type of the RA.
'''
completers_set = {
"params": (prim_complete_params, prim_params_info),
"meta": (prim_complete_meta, meta_attr_info),
"op": (prim_complete_op, op_attr_info),
}
# manage the resource type
words = readline.get_line_buffer().split()
type_word = get_primitive_type(words)
toks = type_word.split(':')
if toks[0] != "ocf":
idx += 1
if idx in (2,3):
return ra_type_list(toks,idx,delimiter)
# create an ra object
ra = None
ra_class,provider,rsc_type = disambiguate_ra_type(type_word)
if ra_type_validate(type_word,ra_class,provider,rsc_type):
ra = RAInfo(ra_class,rsc_type,provider)
keywords = completers_set.keys()
if idx == 4:
if delimiter:
return ' '
return keywords
lastkeyw = get_lastkeyw(words,keywords)
if '=' in words[-1] and readline.get_line_buffer()[-1] != ' ':
if not delimiter and lastkeyw and \
readline.get_line_buffer()[-1] == '=' and len(words[-1]) > 1:
compl_help.help(completers_set[lastkeyw][1],ra)
if delimiter:
return ' '
return ['*']
else:
if lastkeyw:
return completers_set[lastkeyw][0](ra,delimiter)
def property_complete(idx,delimiter = False):
'''
This completer depends on the content of the line, i.e. on
previous tokens.
'''
ra = get_properties_meta()
words = readline.get_line_buffer().split()
if '=' in words[-1] and readline.get_line_buffer()[-1] != ' ':
if not delimiter and \
readline.get_line_buffer()[-1] == '=' and len(words[-1]) > 1:
compl_help.help(prim_params_info,ra)
if delimiter:
return ' '
return ['*']
else:
return prim_complete_params(ra,delimiter)
#
# core completer stuff
#
def lookup_dynamic(fun_list,idx,f_idx,words):
if not fun_list:
return []
if fun_list[f_idx] == loop:
f_idx -= 1
f = fun_list[f_idx]
w = words[0]
wordlist = f(idx)
delimiter = f(idx,1)
if len(wordlist) == 1 and wordlist[0] == '*':
return lookup_dynamic(fun_list,idx+1,f_idx+1,words[1:])
elif len(words) == 1:
return [x+delimiter for x in wordlist if x.startswith(w)]
return lookup_dynamic(fun_list,idx+1,f_idx+1,words[1:])
def lookup_words(ctab,words):
if not ctab:
return []
if type(ctab) == type(()):
return lookup_dynamic(ctab,0,0,words)
if len(words) == 1:
return [x+' ' for x in ctab if x.startswith(words[0])]
elif words[0] in ctab.keys():
return lookup_words(ctab[words[0]],words[1:])
return []
def split_buffer():
p = readline.get_line_buffer()
p = p.replace(':',' ').replace('=',' ')
return p.split()
def completer(txt,state):
levels = Levels.getInstance()
words = split_buffer()
if readline.get_begidx() == readline.get_endidx():
words.append('')
matched = lookup_words(levels.completion_tab,words)
matched.append(None)
return matched[state]
def setup_readline():
readline.set_history_length(100)
readline.parse_and_bind("tab: complete")
readline.set_completer(completer)
readline.set_completer_delims(\
readline.get_completer_delims().replace('-','').replace('/','').replace('=',''))
try: readline.read_history_file(vars.hist_file)
except: pass
#
# a dict of completer functions
# (feel free to add more completers)
#
completer_lists = {
"options" : {
"skill-level" : (skills_list,),
"editor" : None,
"pager" : None,
"user" : None,
"output" : None,
"colorscheme" : None,
"check-frequency" : None,
"check-mode" : None,
"sort-elements" : None,
"save" : None,
"show" : None,
},
"cib" : {
"new" : None,
"delete" : (shadows_list,),
"reset" : (shadows_list,),
"commit" : (shadows_list,),
"use" : (shadows_live_list,),
"diff" : None,
"list" : None,
"import" : None,
"cibstatus" : None,
},
"template" : {
"new" : (null_list,templates_list,loop),
"load" : (config_list,),
"edit" : (config_list,),
"delete" : (config_list,),
"show" : (config_list,),
"apply" : (config_list_method,config_list),
"list" : None,
},
"resource" : {
"status" : (rsc_list,),
"start" : (rsc_list,),
"stop" : (rsc_list,),
"restart" : (rsc_list,),
"promote" : (rsc_list,),
"demote" : (rsc_list,),
"manage" : (rsc_list,),
"unmanage" : (rsc_list,),
"migrate" : (rsc_list,nodes_list),
"unmigrate" : (rsc_list,),
"param" : (rsc_list,attr_cmds),
"meta" : (rsc_list,attr_cmds),
"utilization" : (rsc_list,attr_cmds),
"failcount" : (rsc_list,attr_cmds,nodes_list),
"cleanup" : (rsc_list,nodes_list),
"refresh" : (nodes_list,),
"reprobe" : (nodes_list,),
},
"node" : {
"status" : (nodes_list,),
"show" : (nodes_list,),
"standby" : (nodes_list,),
"online" : (nodes_list,),
"fence" : (nodes_list,),
"delete" : (nodes_list,),
"clearstate" : (nodes_list,),
"attribute" : (nodes_list,attr_cmds),
"utilization" : (nodes_list,attr_cmds),
"status-attr" : (nodes_list,attr_cmds),
},
"ra" : {
"classes" : None,
"list" : None,
"providers" : None,
"meta" : None,
},
"cibstatus" : {
"show" : None,
"save" : None,
"load" : None,
"origin" : None,
"node" : (status_node_list,node_states_list),
"op" : (ra_operations_list,status_rsc_list,lrm_exit_codes_list,lrm_status_codes_list,status_node_list),
"run" : None,
"simulate" : None,
"quorum" : None,
},
"configure" : {
"erase" : None,
"verify" : None,
"refresh" : None,
"ptest" : None,
"commit" : None,
"upgrade" : None,
"show" : (id_xml_list,id_list,loop),
"edit" : (id_xml_list,id_list,loop),
"filter" : (null_list,id_xml_list,id_list,loop),
"delete" : (id_list,loop),
"default-timeouts" : (id_list,loop),
"rename" : (id_list,id_list),
"save" : None,
"load" : None,
"node" : (node_id_list,node_attr_keyw_list),
"primitive" : (null_list,ra_classes_list,primitive_complete_complex,loop),
"group" : (null_list,f_prim_id_list,loop),
"clone" : (null_list,f_children_id_list),
"ms" : (null_list,f_children_id_list),
"location" : (null_list,rsc_id_list),
"colocation" : (null_list,null_list,rsc_id_list,loop),
"order" : (null_list,null_list,rsc_id_list,loop),
"property" : (property_complete,loop),
"rsc_defaults" : (prim_complete_meta,loop),
"op_defaults" : (op_attr_list,loop),
"xml" : None,
"monitor" : None,
"ra" : None,
"cib" : None,
"cibstatus" : None,
"template" : None,
"_test" : None,
"_regtest" : None,
"_objects" : None,
},
}
def get_completer_list(level,cmd):
'Return a list of completer functions.'
try: return completer_lists[level][cmd]
except: return None
compl_help = CompletionHelp()
user_prefs = UserPrefs.getInstance()
vars = Vars.getInstance()
cib_status = CibStatus.getInstance()
cib_factory = CibFactory.getInstance()
# vim:ts=4:sw=4:et:
diff --git a/shell/modules/utils.py b/shell/modules/utils.py
index 13e4db6744..240c37c000 100644
--- a/shell/modules/utils.py
+++ b/shell/modules/utils.py
@@ -1,416 +1,429 @@
# Copyright (C) 2008 Dejan Muhamedagic <dmuhamedagic@suse.de>
#
# 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 software 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 library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
import os
import pwd
from tempfile import mkstemp
import subprocess
import re
import glob
import time
from userprefs import Options, UserPrefs
from msg import *
def is_program(prog):
return subprocess.call("which %s >/dev/null 2>&1"%prog, shell=True) == 0
def ask(msg):
# if there's no terminal, no use asking and default to "no"
if not sys.stdin.isatty():
return False
print_msg = True
while True:
try:
ans = raw_input(msg + ' ')
except EOFError:
ans = 'n'
if not ans or ans[0].lower() not in ('n','y'):
if print_msg:
print "Please answer with y[es] or n[o]"
print_msg = False
else:
return ans[0].lower() == 'y'
def verify_boolean(opt):
return opt.lower() in ("yes","true","on") or \
opt.lower() in ("no","false","off")
def is_boolean_true(opt):
return opt.lower() in ("yes","true","on")
def keyword_cmp(string1, string2):
return string1.lower() == string2.lower()
from UserDict import DictMixin
class odict(DictMixin):
def __init__(self, data=None, **kwdata):
self._keys = []
self._data = {}
def __setitem__(self, key, value):
if key not in self._data:
self._keys.append(key)
self._data[key] = value
def __getitem__(self, key):
if key not in self._data:
return self._data[key.lower()]
return self._data[key]
def __delitem__(self, key):
del self._data[key]
self._keys.remove(key)
def keys(self):
return list(self._keys)
def copy(self):
copyDict = odict()
copyDict._data = self._data.copy()
copyDict._keys = self._keys[:]
return copyDict
class olist(list):
def __init__(self, keys):
#print "Init %s" % (repr(keys))
super(olist, self).__init__()
for key in keys:
self.append(key)
self.append(key.upper())
def setup_help_aliases(obj):
for cmd in obj.cmd_aliases.keys():
for alias in obj.cmd_aliases[cmd]:
if obj.help_table:
obj.help_table[alias] = obj.help_table[cmd]
def setup_aliases(obj):
for cmd in obj.cmd_aliases.keys():
for alias in obj.cmd_aliases[cmd]:
obj.cmd_table[alias] = obj.cmd_table[cmd]
def getpwdent():
try: euid = os.geteuid()
except Exception, msg:
common_err(msg)
return None
try: pwdent = pwd.getpwuid(euid)
except Exception, msg:
common_err(msg)
return None
return pwdent
def getuser():
user = os.getenv("USER")
if not user:
try: return getpwdent()[0]
except: return None
else:
return user
def gethomedir():
homedir = os.getenv("HOME")
if not homedir:
try: return getpwdent()[5]
except: return None
else:
return homedir
def os_types_list(path):
l = []
for f in glob.glob(path):
if os.access(f,os.X_OK) and os.path.isfile(f):
a = f.split("/")
l.append(a[-1])
return l
+def listtemplates():
+ l = []
+ for f in os.listdir(vars.tmpl_dir):
+ if os.path.isfile("%s/%s" % (vars.tmpl_dir,f)):
+ l.append(f)
+ return l
+def listconfigs():
+ l = []
+ for f in os.listdir(vars.tmpl_conf_dir):
+ if os.path.isfile("%s/%s" % (vars.tmpl_conf_dir,f)):
+ l.append(f)
+ return l
+
def add_sudo(cmd):
if user_prefs.crm_user:
return "sudo -E -u %s %s"%(user_prefs.crm_user,cmd)
return cmd
def pipe_string(cmd,s):
rc = -1 # command failed
cmd = add_sudo(cmd)
p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
try:
p.communicate(s)
p.wait()
rc = p.returncode
except IOError, msg:
common_err(msg)
return rc
def filter_string(cmd,s,stderr_on = True):
rc = -1 # command failed
if stderr_on:
stderr = None
else:
stderr = subprocess.PIPE
cmd = add_sudo(cmd)
p = subprocess.Popen(cmd, shell=True, \
stdin = subprocess.PIPE, \
stdout = subprocess.PIPE, stderr = stderr)
try:
outp = p.communicate(s)[0]
p.wait()
rc = p.returncode
except IOError, msg:
common_err(msg)
return rc,outp
def str2tmp(s):
'''
Write the given string to a temporary file. Return the name
of the file.
'''
fd,tmp = mkstemp()
try: f = os.fdopen(fd,"w")
except IOError, msg:
common_err(msg)
return
f.write(s)
f.close()
return tmp
def str2file(s,fname):
'''
Write a string to a file.
'''
try: f = open(fname,"w")
except IOError, msg:
common_err(msg)
return False
f.write(s)
f.close()
return True
def is_filename_sane(name):
if re.search("['`/#*?$\[\]]",name):
common_err("%s: bad name"%name)
return False
return True
def is_name_sane(name):
if re.search("[']",name):
common_err("%s: bad name"%name)
return False
return True
def is_value_sane(name):
if re.search("[']",name):
common_err("%s: bad name"%name)
return False
return True
def show_dot_graph(dotfile):
p = subprocess.Popen("%s %s" % (user_prefs.dotty,dotfile), shell=True, bufsize=0, stdin=None, stdout=None, stderr=None, close_fds=True)
common_info("starting %s to show transition graph"%user_prefs.dotty)
def ext_cmd(cmd):
if options.regression_tests:
print ".EXT", cmd
return subprocess.call(add_sudo(cmd), shell=True)
def get_stdout(cmd, stderr_on = True):
'''
Run a cmd, return stdin output.
stderr_on controls whether to show output which comes on stderr.
'''
if stderr_on:
stderr = None
else:
stderr = subprocess.PIPE
proc = subprocess.Popen(cmd, shell = True, \
stdout = subprocess.PIPE, stderr = stderr)
outp = proc.communicate()[0]
proc.wait()
outp = outp.strip()
return outp
def stdout2list(cmd, stderr_on = True):
'''
Run a cmd, fetch output, return it as a list of lines.
stderr_on controls whether to show output which comes on stderr.
'''
s = get_stdout(add_sudo(cmd), stderr_on)
return s.split('\n')
def wait4dc(what = "", show_progress = True):
'''
Wait for the DC to get into the S_IDLE state. This should be
invoked only after a CIB modification which would exercise
the PE. Parameter "what" is whatever the caller wants to be
printed if showing progress.
It is assumed that the DC is already in a different state,
usually it should be either PENGINE or TRANSITION. This
assumption may not be true, but there's a high chance that it
is since crmd should be faster to move through states than
this shell.
Further, it may also be that crmd already calculated the new
graph, did transition, and went back to the idle state. This
may in particular be the case if the transition turned out to
be empty.
Tricky. Though in practice it shouldn't be an issue.
There's no timeout, as we expect the DC to eventually becomes
idle.
'''
cmd = "crmadmin -D"
s = get_stdout(add_sudo(cmd))
if not s.startswith("Designated"):
common_warn("%s unexpected output: %s" % (cmd,s))
return False
dc = s.split()[-1]
if not dc:
common_warn("can't find DC in: %s" % s)
return False
cmd = "crmadmin -S %s" % dc
cnt = 0
output_started = 0
while True:
s = get_stdout(add_sudo(cmd))
if not s.startswith("Status"):
common_warn("%s unexpected output: %s" % (cmd,s))
return False
try: dc_status = s.split()[-2]
except:
common_warn("%s unexpected output: %s" % (cmd,s))
return False
if dc_status == "S_IDLE":
if output_started:
sys.stderr.write(" done\n")
return True
time.sleep(0.1)
if show_progress:
cnt += 1
if cnt % 10 == 0:
if not output_started:
output_started = 1
sys.stderr.write("waiting for %s to finish " % what)
sys.stderr.write(".")
def is_id_valid(id):
"""
Verify that the id follows the definition:
http://www.w3.org/TR/1999/REC-xml-names-19990114/#ns-qualnames
"""
if not id:
return False
id_re = "^[A-Za-z_][\w._-]*$"
return re.match(id_re,id)
def check_filename(fname):
"""
Verify that the string is a filename.
"""
fname_re = "^[^/]+$"
return re.match(fname_re,id)
def is_process(s):
proc = subprocess.Popen("ps -e -o pid,command | grep -qs '%s'" % s, \
shell=True, stdout=subprocess.PIPE)
proc.wait()
return proc.returncode == 0
def cluster_stack():
if is_process("heartbeat:.[m]aster"):
return "heartbeat"
elif is_process("[a]isexec"):
return "openais"
return ""
def edit_file(fname):
'Edit a file.'
if not fname:
return
if not user_prefs.editor:
return
return ext_cmd("%s %s" % (user_prefs.editor,fname))
def page_string(s):
'Write string through a pager.'
if not s:
return
w,h = get_winsize()
if s.count('\n') <= h:
print s
elif not user_prefs.pager or not options.interactive:
print s
else:
opts = ""
if user_prefs.pager == "less":
opts = "-R"
pipe_string("%s %s" % (user_prefs.pager,opts), s)
def get_winsize():
try:
import curses
curses.setupterm()
w = curses.tigetnum('cols')
h = curses.tigetnum('lines')
except:
try:
w = os.environ['COLS']
h = os.environ['LINES']
except:
w = 80; h = 25
return w,h
def multicolumn(l):
'''
A ls-like representation of a list of strings.
A naive approach.
'''
min_gap = 2
w,h = get_winsize()
max_len = 8
for s in l:
if len(s) > max_len:
max_len = len(s)
cols = w/(max_len + min_gap) # approx.
col_len = w/cols
for i in range(len(l)/cols + 1):
s = ''
for j in range(i*cols,(i+1)*cols):
if not j < len(l):
break
if not s:
s = "%-*s" % (col_len,l[j])
elif (j+1)%cols == 0:
s = "%s%s" % (s,l[j])
else:
s = "%s%-*s" % (s,col_len,l[j])
if s:
print s
def find_value(pl,name):
for n,v in pl:
if n == name:
return v
return None
def lines2cli(s):
'''
Convert a string into a list of lines. Replace continuation
characters. Strip white space, left and right. Drop empty lines.
'''
cl = []
l = s.split('\n')
cum = []
for p in l:
p = p.strip()
if p.endswith('\\'):
p = p.rstrip('\\')
cum.append(p)
else:
cum.append(p)
cl.append(''.join(cum).strip())
cum = []
if cum: # in case s ends with backslash
cl.append(''.join(cum))
return [x for x in cl if x]
user_prefs = UserPrefs.getInstance()
options = Options.getInstance()
# vim:ts=4:sw=4:et:
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:18 PM (12 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002566
Default Alt Text
(27 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment