Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions qubesadmin/tools/qvm_ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,14 +404,15 @@ class Table(object):
:param list colnames: Names of the columns (need not to be uppercase).
'''
def __init__(self, domains, colnames, spinner, *, raw_data=False,
tree_sorted=False, sort_order='NAME', reverse_sort=False,
ignore_case=False):
tree_sorted=False, ttree_sorted=False, sort_order='NAME',
reverse_sort=False, ignore_case=False):
self.domains = domains
self.columns = tuple(Column.columns[col.upper().replace('_', '-')]
for col in colnames)
self.spinner = spinner
self.raw_data = raw_data
self.tree_sorted = tree_sorted
self.ttree_sorted = ttree_sorted
self.sort_order = sort_order
self.reverse_sort = reverse_sort
self.ignore_case = ignore_case
Expand All @@ -424,7 +425,7 @@ def get_row(self, vm, insertion=0):
'''Get single table row data (all columns for one domain).'''
ret = []
for col in self.columns:
if self.tree_sorted and col.ls_head == 'NAME':
if (self.tree_sorted or self.ttree_sorted) and col.ls_head == 'NAME':
ret.append(col.cell(vm, insertion))
else:
ret.append(col.cell(vm))
Expand Down Expand Up @@ -474,6 +475,43 @@ def sort_to_tree(self, domains):

return tree

def sort_to_ttree(self, domains):
'''Sort domains as a template tree. It returns a list of tuples. Each
tuple stores the level of the tree and the vm object.

:param list() domains: The domains which will be sorted
:return list(tuple()) tree: returns a list of tuple(level, vm)
'''
tree=[]
for dom in sorted(domains):
try:
if not dom.template:
tree.append((0,dom))
domains.remove(dom)
except AttributeError:
tree.append((0,dom))
domains.remove(dom)

level = 0
while len(domains) > 0:
last_len = len(domains)
for dom in sorted(domains):
try:
# Insert before (index of the template entry) + 1,
# i.e. after parent. What if parent entry is the last entry?
tree.insert(
tree.index((level,dom.template))+1,
(level+1,dom))
domains.remove(dom)
# Pass if parent isn't in the tree yet
except ValueError:
pass
if len(domains) >= last_len:
raise Exception("sort_to_ttree: While loop is stuck!")
level += 1

return tree

def write_table(self, stream=sys.stdout):
'''Sort & write whole table to file-like object.

Expand All @@ -500,6 +538,10 @@ def sort_numeric(field: str) -> int:
insertion_vm_list = self.sort_to_tree(self.domains)
for insertion, vm in insertion_vm_list:
table_data.append(self.get_row(vm, insertion))
elif self.ttree_sorted:
insertion_vm_list = self.sort_to_ttree(self.domains)
for insertion, vm in insertion_vm_list:
table_data.append(self.get_row(vm, insertion))
else:
for vm in sorted(self.domains):
try:
Expand Down Expand Up @@ -651,6 +693,10 @@ def get_parser():
action='store_const', const='tree',
help='sort domain list as network tree')

parser.add_argument('--ttree', '-T',
action='store_const', const='ttree',
help='sort domain list as template tree')

parser_format.add_argument('--raw-data', action='store_true',
help='Display specify data of specified VMs. Intended for '
'bash-parsing.')
Expand Down Expand Up @@ -906,7 +952,7 @@ def main(args=None, app=None):
if matches_power_states(d, **pwrstates)]

table = Table(domains=domains, colnames=columns, spinner=spinner,
raw_data=args.raw_data, tree_sorted=args.tree,
raw_data=args.raw_data, tree_sorted=args.tree, ttree_sorted=args.tree,
sort_order=args.sort.upper(), reverse_sort=args.reverse,
ignore_case=args.ignore_case)
table.write_table(sys.stdout)
Expand Down