Skip to content

Added more error handling around table output #2155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
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
69 changes: 22 additions & 47 deletions SoftLayer/CLI/block/detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,77 +31,52 @@ def cli(env, volume_id):
table.add_row(['Username', block_volume['username']])
table.add_row(['Type', storage_type])
table.add_row(['Capacity (GB)', capacity])
table.add_row(['LUN Id', "%s" % block_volume['lunId']])
table.add_row(['LUN Id', block_volume['lunId']])

if block_volume.get('provisionedIops'):
table.add_row(['IOPs', float(block_volume['provisionedIops'])])
table.add_row(['IOPs', block_volume['provisionedIops']])

if block_volume.get('storageTierLevel'):
table.add_row([
'Endurance Tier',
block_volume['storageTierLevel'],
])

table.add_row([
'Data Center',
block_volume['serviceResource']['datacenter']['name'],
])
table.add_row([
'Target IP',
block_volume['serviceResourceBackendIpAddress'],
])
table.add_row(['Endurance Tier', block_volume['storageTierLevel']])

table.add_row(['Data Center', block_volume['serviceResource']['datacenter']['name']])
table.add_row(['Target IP', block_volume['serviceResourceBackendIpAddress']])

if block_volume['snapshotCapacityGb']:
table.add_row([
'Snapshot Capacity (GB)',
block_volume['snapshotCapacityGb'],
])
table.add_row(['Snapshot Capacity (GB)', block_volume['snapshotCapacityGb']])
if 'snapshotSizeBytes' in block_volume['parentVolume']:
table.add_row([
'Snapshot Used (Bytes)',
block_volume['parentVolume']['snapshotSizeBytes'],
])
table.add_row(['Snapshot Used (Bytes)', block_volume['parentVolume']['snapshotSizeBytes']])

table.add_row(['# of Active Transactions', "%i"
% block_volume['activeTransactionCount']])
table.add_row(['# of Active Transactions', block_volume['activeTransactionCount']])

if block_volume['activeTransactions']:
for trans in block_volume['activeTransactions']:
if 'transactionStatus' in trans and 'friendlyName' in trans['transactionStatus']:
table.add_row(['Ongoing Transaction', trans['transactionStatus']['friendlyName']])

table.add_row(['Replicant Count', "%u" % block_volume.get('replicationPartnerCount', 0)])
table.add_row(['Replicant Count', block_volume.get('replicationPartnerCount', 0)])

if block_volume['replicationPartnerCount'] > 0:
# This if/else temporarily handles a bug in which the SL API
# returns a string or object for 'replicationStatus'; it seems that
# the type is string for File volumes and object for Block volumes
if 'message' in block_volume['replicationStatus']:
table.add_row(['Replication Status', "%s"
% block_volume['replicationStatus']['message']])
table.add_row(['Replication Status', block_volume['replicationStatus']['message']])
else:
table.add_row(['Replication Status', "%s"
% block_volume['replicationStatus']])
table.add_row(['Replication Status', block_volume['replicationStatus']])

replicant_table = formatting.Table(['Id', 'Username', 'Target', 'Location', 'Schedule'])
replicant_table.align['Name'] = 'r'
replicant_table.align['Value'] = 'l'
for replicant in block_volume['replicationPartners']:
replicant_table = formatting.Table(['Name',
'Value'])
replicant_table.add_row(['Replicant Id', replicant['id']])
replicant_table.add_row([
'Volume Name',
utils.lookup(replicant, 'username')])
replicant_table.add_row([
'Target IP',
utils.lookup(replicant, 'serviceResourceBackendIpAddress')])
replicant_table.add_row([
'Data Center',
utils.lookup(replicant,
'serviceResource', 'datacenter', 'name')])
replicant_table.add_row([
'Schedule',
utils.lookup(replicant,
'replicationSchedule', 'type', 'keyname')])
table.add_row(['Replicant Volumes', replicant_table])
replicant.get('id'),
utils.lookup(replicant, 'username'),
utils.lookup(replicant, 'serviceResourceBackendIpAddress'),
utils.lookup(replicant, 'serviceResource', 'datacenter', 'name'),
utils.lookup(replicant, 'replicationSchedule', 'type', 'keyname')
])
table.add_row(['Replicant Volumes', replicant_table])

if block_volume.get('originalVolumeSize'):
original_volume_info = formatting.Table(['Property', 'Value'])
Expand Down
15 changes: 12 additions & 3 deletions SoftLayer/CLI/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ def __init__(self, code=0, *args):
self.code = code

def __str__(self):
return "<CLIHalt code=%s msg=%s>" % (self.code,
getattr(self, 'message'))

message = getattr(self, 'message')
return f"<CLIHalt code={self.code} msg={message}>"
__repr__ = __str__


Expand All @@ -29,10 +28,20 @@ def __init__(self, msg, *args):
super().__init__(code=2, *args)
self.message = msg

def __str__(self):
message = getattr(self, 'message')
return f"<CLIAbort code={self.code} msg={message}>"
__repr__ = __str__


class ArgumentError(CLIAbort):
"""Halt the execution of the command because of invalid arguments."""

def __init__(self, msg, *args):
super().__init__(msg, *args)
self.message = "Argument Error: %s" % msg

def __str__(self):
message = getattr(self, 'message')
return f"<ArgumentError code={self.code} msg={message}>"
__repr__ = __str__
83 changes: 23 additions & 60 deletions SoftLayer/CLI/file/detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,54 +37,27 @@ def cli(env, volume_id):
table.add_row(['Type', storage_type])
table.add_row(['Capacity (GB)', get_capacity(file_volume)])

used_space = int(file_volume['bytesUsed']) \
if file_volume['bytesUsed'] else 0
if used_space < (1 << 10):
table.add_row(['Used Space', "%dB" % used_space])
elif used_space < (1 << 20):
table.add_row(['Used Space', "%dKB" % (used_space / (1 << 10))])
elif used_space < (1 << 30):
table.add_row(['Used Space', "%dMB" % (used_space / (1 << 20))])
else:
table.add_row(['Used Space', "%dGB" % (used_space / (1 << 30))])
used_space = formatting.convert_sizes(file_volume.get('bytes_used', 0), "GB", False)
table.add_row(['Used Space', used_space])

if file_volume.get('provisionedIops'):
table.add_row(['IOPs', float(file_volume['provisionedIops'])])
table.add_row(['IOPs', file_volume['provisionedIops']])

if file_volume.get('storageTierLevel'):
table.add_row([
'Endurance Tier',
file_volume['storageTierLevel'],
])

table.add_row([
'Data Center',
file_volume['serviceResource']['datacenter']['name'],
])
table.add_row([
'Target IP',
file_volume['serviceResourceBackendIpAddress'],
])
table.add_row(['Endurance Tier', file_volume['storageTierLevel']])

table.add_row(['Data Center', file_volume['serviceResource']['datacenter']['name']])
table.add_row(['Target IP', file_volume['serviceResourceBackendIpAddress']])

if file_volume['fileNetworkMountAddress']:
table.add_row([
'Mount Address',
file_volume['fileNetworkMountAddress'],
])
table.add_row(['Mount Address', file_volume['fileNetworkMountAddress']])

if file_volume['snapshotCapacityGb']:
table.add_row([
'Snapshot Capacity (GB)',
file_volume['snapshotCapacityGb'],
])
table.add_row(['Snapshot Capacity (GB)', file_volume['snapshotCapacityGb']])
if 'snapshotSizeBytes' in file_volume['parentVolume']:
table.add_row([
'Snapshot Used (Bytes)',
file_volume['parentVolume']['snapshotSizeBytes'],
])
table.add_row(['Snapshot Used (Bytes)', file_volume['parentVolume']['snapshotSizeBytes']])

table.add_row(['# of Active Transactions', "%i"
% file_volume['activeTransactionCount']])
table.add_row(["# of Active Transactions", file_volume['activeTransactionCount']])

if file_volume['activeTransactions']:
for trans in file_volume['activeTransactions']:
Expand All @@ -98,32 +71,22 @@ def cli(env, volume_id):
# returns a string or object for 'replicationStatus'; it seems that
# the type is string for File volumes and object for Block volumes
if 'message' in file_volume['replicationStatus']:
table.add_row(['Replication Status', "%s"
% file_volume['replicationStatus']['message']])
table.add_row(['Replication Status', file_volume['replicationStatus']['message']])
else:
table.add_row(['Replication Status', "%s"
% file_volume['replicationStatus']])
table.add_row(['Replication Status', file_volume['replicationStatus']])

replicant_list = []
replicant_table = formatting.Table(['Id', 'Username', 'Target', 'Location', 'Schedule'])
replicant_table.align['Name'] = 'r'
replicant_table.align['Value'] = 'l'
for replicant in file_volume['replicationPartners']:
replicant_table = formatting.Table(['Replicant ID',
replicant['id']])
replicant_table.add_row([
'Volume Name',
utils.lookup(replicant, 'username')])
replicant_table.add_row([
'Target IP',
utils.lookup(replicant, 'serviceResourceBackendIpAddress')])
replicant_table.add_row([
'Data Center',
utils.lookup(replicant,
'serviceResource', 'datacenter', 'name')])
replicant_table.add_row([
'Schedule',
utils.lookup(replicant,
'replicationSchedule', 'type', 'keyname')])
replicant_list.append(replicant_table)
table.add_row(['Replicant Volumes', replicant_list])
replicant.get('id'),
utils.lookup(replicant, 'username'),
utils.lookup(replicant, 'serviceResourceBackendIpAddress'),
utils.lookup(replicant, 'serviceResource', 'datacenter', 'name'),
utils.lookup(replicant, 'replicationSchedule', 'type', 'keyname')
])
table.add_row(['Replicant Volumes', replicant_table])

if file_volume.get('originalVolumeSize'):
original_volume_info = formatting.Table(['Property', 'Value'])
Expand Down
11 changes: 10 additions & 1 deletion SoftLayer/CLI/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import click
from rich import box
from rich.errors import NotRenderableError
from rich.table import Table as rTable

from SoftLayer.CLI import exceptions
Expand Down Expand Up @@ -392,7 +393,15 @@ def prettytable(self, fmt='table', theme=None):
table.add_column(col, justify=justify, style=style)

for row in self.rows:
table.add_row(*row)
try:
table.add_row(*row)
# Generally you will see this if one of the columns in the row is a list or dict
except NotRenderableError:
forced_row = []
for i in row:
forced_row.append(str(i))
table.add_row(*forced_row)

return table


Expand Down
103 changes: 103 additions & 0 deletions SoftLayer/fixtures/SoftLayer_Network_Storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,107 @@
'storageType': {
'keyName': 'ENDURANCE_BLOCK_STORAGE'
}
}


FILE_DETAIL_ISSUE2154 = {
"capacityGb": 150,
"id": 609491933,
"username": "SL02SV1414935_187",
"activeTransactionCount": 0,
"replicationPartnerCount": 1,
"fileNetworkMountAddress": "fsf-natestdal0505-fcb-fz.service.softlayer.com:/SL02SV1414935_187/data01",
"originalVolumeSize": "20",
"provisionedIops": "2000",
"replicationStatus": "FAILOVER_COMPLETED",
"serviceResourceBackendIpAddress": "fsf-natestdal0505-fcb-fz.service.softlayer.com",
"snapshotCapacityGb": "5",
"activeTransactions": [
{
"createDate": "",
"elapsedSeconds": 111763,
"guestId": "",
"hardwareId": "",
"id": "",
"modifyDate": "",
"statusChangeDate": "",
"transactionGroup": {
"name": "Volume Modification"
},
"transactionStatus": {
"friendlyName": "In Progress"
}
}
],
"parentVolume": {
"accountId": 1414935,
"capacityGb": 120,
"createDate": "2024-05-16T02:28:02-05:00",
"guestId": "",
"hardwareId": "",
"hostId": "",
"id": 609491967,
"nasType": "SNAPSHOT",
"notes": "vol_duplicate_snapshot_2024-05-16_0228",
"serviceProviderId": 1,
"storageTypeId": "16",
"upgradableFlag": True,
"username": "SL02SV1414935_187",
"serviceResourceBackendIpAddress": "fsf-natestdal0505-fcb-fz.service.softlayer.com",
"serviceResourceName": "Storage Type 02 Aggregate natestdal0505-fc-d",
"snapshotSizeBytes": "0"
},
"replicationPartners": [
{
"id": 609491945,
"username": "SL02SV1414935_187_REP_1",
"serviceResourceBackendIpAddress": "fsf-natestdal0505-ffb-fz.service.softlayer.com",
"replicationSchedule": {
"active": 1,
"createDate": "2024-05-16T01:20:19-05:00",
"id": 666339,
"modifyDate": "",
"name": "SL02SV1414935_187_HOURLY_REP",
"partnershipId": "",
"typeId": 32,
"volumeId": 609491933,
"type": {
"keyname": "REPLICATION_HOURLY"
}
},
"serviceResource": {
"backendIpAddress": "fsf-natestdal0505-ffb-fz.service.softlayer.com",
"id": 57365,
"name": "Storage Type 02 Aggregate natestdal0505-ff-d",
"datacenter": {
"name": "dal10"
},
"type": {
"type": "NETAPP_STOR_AGGR"
}
}
}
],
"serviceResource": {
"backendIpAddress": "fsf-natestdal0505-fcb-fz.service.softlayer.com",
"id": 52292,
"name": "Storage Type 02 Aggregate natestdal0505-fc-d",
"attributes": [
{
"value": "2",
"attributeType": {
"keyname": "STAAS_VERSION"
}
}
],
"datacenter": {
"name": "lon02"
},
"type": {
"type": "NETAPP_STOR_AGGR"
}
},
"storageType": {
"keyName": "PERFORMANCE_FILE_STORAGE"
}
}
1 change: 1 addition & 0 deletions SoftLayer/testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def setUp(self): # NOQA
self.env = environment.Environment()
self.env.client = self.client
self.set_up()
self.maxDiff = None

def tearDown(self): # NOQA
super().tearDown()
Expand Down
Loading
Loading