Skip to content

Commit 0803951

Browse files
Merge pull request #1150 from allmightyspiff/issues1003
Bandwidth usage details for vs and server
2 parents 3bebf3a + a86f106 commit 0803951

24 files changed

+1022
-201
lines changed

.travis.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1+
# https://docs.travis-ci.com/user/languages/python/#python-37-and-higher
2+
dist: xenial
13
language: python
24
sudo: false
35
matrix:
46
include:
5-
- python: "2.7"
6-
env: TOX_ENV=py27
77
- python: "3.5"
88
env: TOX_ENV=py35
99
- python: "3.6"
1010
env: TOX_ENV=py36
11-
- python: "pypy2.7-5.8.0"
11+
- python: "3.7"
12+
env: TOX_ENV=py37
13+
- python: "pypy3.5"
1214
env: TOX_ENV=pypy
13-
- python: "2.7"
15+
- python: "3.6"
1416
env: TOX_ENV=analysis
15-
- python: "2.7"
17+
- python: "3.6"
1618
env: TOX_ENV=coverage
1719
install:
1820
- pip install tox
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Get details for a hardware device."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import helpers
9+
from SoftLayer.CLI.virt.bandwidth import create_bandwidth_table
10+
11+
12+
@click.command()
13+
@click.argument('identifier')
14+
@click.option('--start_date', '-s', type=click.STRING, required=True,
15+
help="Start Date YYYY-MM-DD, YYYY-MM-DDTHH:mm:ss,")
16+
@click.option('--end_date', '-e', type=click.STRING, required=True,
17+
help="End Date YYYY-MM-DD, YYYY-MM-DDTHH:mm:ss")
18+
@click.option('--summary_period', '-p', type=click.INT, default=3600, show_default=True,
19+
help="300, 600, 1800, 3600, 43200 or 86400 seconds")
20+
@click.option('--quite_summary', '-q', is_flag=True, default=False, show_default=True,
21+
help="Only show the summary table")
22+
@environment.pass_env
23+
def cli(env, identifier, start_date, end_date, summary_period, quite_summary):
24+
"""Bandwidth data over date range. Bandwidth is listed in GB
25+
26+
Using just a date might get you times off by 1 hour, use T00:01 to get just the specific days data
27+
Timezones can also be included with the YYYY-MM-DDTHH:mm:ss.00000-HH:mm format.
28+
29+
Due to some rounding and date alignment details, results here might be slightly different than
30+
results in the control portal.
31+
32+
Example::
33+
34+
slcli hw bandwidth 1234 -s 2019-05-01T00:01 -e 2019-05-02T00:00:01.00000-12:00
35+
"""
36+
hardware = SoftLayer.HardwareManager(env.client)
37+
hardware_id = helpers.resolve_id(hardware.resolve_ids, identifier, 'hardware')
38+
data = hardware.get_bandwidth_data(hardware_id, start_date, end_date, None, summary_period)
39+
40+
title = "Bandwidth Report: %s - %s" % (start_date, end_date)
41+
table, sum_table = create_bandwidth_table(data, summary_period, title)
42+
43+
env.fout(sum_table)
44+
if not quite_summary:
45+
env.fout(table)

SoftLayer/CLI/hardware/detail.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ def cli(env, identifier, passwords, price):
5757

5858
table.add_row(['vlans', vlan_table])
5959

60+
bandwidth = hardware.get_bandwidth_allocation(hardware_id)
61+
bw_table = _bw_table(bandwidth)
62+
table.add_row(['Bandwidth', bw_table])
63+
6064
if result.get('notes'):
6165
table.add_row(['notes', result['notes']])
6266

@@ -85,3 +89,17 @@ def cli(env, identifier, passwords, price):
8589
table.add_row(['tags', formatting.tags(result['tagReferences'])])
8690

8791
env.fout(table)
92+
93+
94+
def _bw_table(bw_data):
95+
"""Generates a bandwidth useage table"""
96+
table = formatting.Table(['Type', 'In GB', 'Out GB', 'Allotment'])
97+
for bw_point in bw_data.get('useage'):
98+
bw_type = 'Private'
99+
allotment = 'N/A'
100+
if bw_point['type']['alias'] == 'PUBLIC_SERVER_BW':
101+
bw_type = 'Public'
102+
allotment = bw_data['allotment'].get('amount', '-')
103+
104+
table.add_row([bw_type, bw_point['amountIn'], bw_point['amountOut'], allotment])
105+
return table

SoftLayer/CLI/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
('account:summary', 'SoftLayer.CLI.account.summary:cli'),
2020

2121
('virtual', 'SoftLayer.CLI.virt'),
22+
('virtual:bandwidth', 'SoftLayer.CLI.virt.bandwidth:cli'),
2223
('virtual:cancel', 'SoftLayer.CLI.virt.cancel:cli'),
2324
('virtual:capture', 'SoftLayer.CLI.virt.capture:cli'),
2425
('virtual:create', 'SoftLayer.CLI.virt.create:cli'),
@@ -213,6 +214,7 @@
213214
('rwhois:show', 'SoftLayer.CLI.rwhois.show:cli'),
214215

215216
('hardware', 'SoftLayer.CLI.hardware'),
217+
('hardware:bandwidth', 'SoftLayer.CLI.hardware.bandwidth:cli'),
216218
('hardware:cancel', 'SoftLayer.CLI.hardware.cancel:cli'),
217219
('hardware:cancel-reasons', 'SoftLayer.CLI.hardware.cancel_reasons:cli'),
218220
('hardware:create', 'SoftLayer.CLI.hardware.create:cli'),

SoftLayer/CLI/virt/bandwidth.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""Get details for a hardware device."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
from SoftLayer.CLI import helpers
10+
from SoftLayer import utils
11+
12+
13+
@click.command()
14+
@click.argument('identifier')
15+
@click.option('--start_date', '-s', type=click.STRING, required=True,
16+
help="Start Date YYYY-MM-DD, YYYY-MM-DDTHH:mm:ss,")
17+
@click.option('--end_date', '-e', type=click.STRING, required=True,
18+
help="End Date YYYY-MM-DD, YYYY-MM-DDTHH:mm:ss")
19+
@click.option('--summary_period', '-p', type=click.INT, default=3600, show_default=True,
20+
help="300, 600, 1800, 3600, 43200 or 86400 seconds")
21+
@click.option('--quite_summary', '-q', is_flag=True, default=False, show_default=True,
22+
help="Only show the summary table")
23+
@environment.pass_env
24+
def cli(env, identifier, start_date, end_date, summary_period, quite_summary):
25+
"""Bandwidth data over date range. Bandwidth is listed in GB
26+
27+
Using just a date might get you times off by 1 hour, use T00:01 to get just the specific days data
28+
Timezones can also be included with the YYYY-MM-DDTHH:mm:ss.00000-HH:mm format.
29+
30+
Due to some rounding and date alignment details, results here might be slightly different than
31+
results in the control portal.
32+
33+
Example::
34+
35+
slcli hw bandwidth 1234 -s 2019-05-01T00:01 -e 2019-05-02T00:00:01.00000-12:00
36+
"""
37+
vsi = SoftLayer.VSManager(env.client)
38+
vsi_id = helpers.resolve_id(vsi.resolve_ids, identifier, 'VS')
39+
data = vsi.get_bandwidth_data(vsi_id, start_date, end_date, None, summary_period)
40+
41+
title = "Bandwidth Report: %s - %s" % (start_date, end_date)
42+
table, sum_table = create_bandwidth_table(data, summary_period, title)
43+
44+
env.fout(sum_table)
45+
if not quite_summary:
46+
env.fout(table)
47+
48+
49+
def create_bandwidth_table(data, summary_period, title="Bandwidth Report"):
50+
"""Create 2 tables, bandwidth and sumamry. Used here and in hw bandwidth command"""
51+
52+
formatted_data = {}
53+
for point in data:
54+
key = utils.clean_time(point['dateTime'])
55+
data_type = point['type']
56+
# conversion from byte to megabyte
57+
value = round(float(point['counter']) / 2 ** 20, 4)
58+
if formatted_data.get(key) is None:
59+
formatted_data[key] = {}
60+
formatted_data[key][data_type] = float(value)
61+
62+
table = formatting.Table(['Date', 'Pub In', 'Pub Out', 'Pri In', 'Pri Out'], title=title)
63+
64+
sum_table = formatting.Table(['Type', 'Sum GB', 'Average MBps', 'Max GB', 'Max Date'], title="Summary")
65+
66+
# Required to specify keyName because getBandwidthTotals returns other counter types for some reason.
67+
bw_totals = [
68+
{'keyName': 'publicIn_net_octet', 'sum': 0.0, 'max': 0, 'name': 'Pub In'},
69+
{'keyName': 'publicOut_net_octet', 'sum': 0.0, 'max': 0, 'name': 'Pub Out'},
70+
{'keyName': 'privateIn_net_octet', 'sum': 0.0, 'max': 0, 'name': 'Pri In'},
71+
{'keyName': 'privateOut_net_octet', 'sum': 0.0, 'max': 0, 'name': 'Pri Out'},
72+
]
73+
74+
for point in formatted_data:
75+
new_row = [point]
76+
for bw_type in bw_totals:
77+
counter = formatted_data[point].get(bw_type['keyName'], 0)
78+
new_row.append(mb_to_gb(counter))
79+
bw_type['sum'] = bw_type['sum'] + counter
80+
if counter > bw_type['max']:
81+
bw_type['max'] = counter
82+
bw_type['maxDate'] = point
83+
table.add_row(new_row)
84+
85+
for bw_type in bw_totals:
86+
total = bw_type.get('sum', 0.0)
87+
average = 0
88+
if total > 0:
89+
average = round(total / len(formatted_data) / summary_period, 4)
90+
sum_table.add_row([
91+
bw_type.get('name'),
92+
mb_to_gb(total),
93+
average,
94+
mb_to_gb(bw_type.get('max')),
95+
bw_type.get('maxDate')
96+
])
97+
98+
return table, sum_table
99+
100+
101+
def mb_to_gb(mbytes):
102+
"""Converts a MegaByte int to GigaByte. mbytes/2^10"""
103+
return round(mbytes / 2 ** 10, 4)

SoftLayer/CLI/virt/detail.py

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -39,65 +39,42 @@ def cli(env, identifier, passwords=False, price=False):
3939
table.add_row(['domain', result['domain']])
4040
table.add_row(['fqdn', result['fullyQualifiedDomainName']])
4141
table.add_row(['status', formatting.FormattedItem(
42-
result['status']['keyName'] or formatting.blank(),
43-
result['status']['name'] or formatting.blank()
42+
result['status']['keyName'],
43+
result['status']['name']
4444
)])
4545
table.add_row(['state', formatting.FormattedItem(
4646
utils.lookup(result, 'powerState', 'keyName'),
4747
utils.lookup(result, 'powerState', 'name'),
4848
)])
4949
table.add_row(['active_transaction', formatting.active_txn(result)])
50-
table.add_row(['datacenter',
51-
result['datacenter']['name'] or formatting.blank()])
50+
table.add_row(['datacenter', result['datacenter']['name'] or formatting.blank()])
5251
_cli_helper_dedicated_host(env, result, table)
5352
operating_system = utils.lookup(result,
5453
'operatingSystem',
5554
'softwareLicense',
5655
'softwareDescription') or {}
57-
table.add_row(['os', operating_system.get('name') or formatting.blank()])
58-
table.add_row(['os_version',
59-
operating_system.get('version') or formatting.blank()])
56+
table.add_row(['os', operating_system.get('name', '-')])
57+
table.add_row(['os_version', operating_system.get('version', '-')])
6058
table.add_row(['cores', result['maxCpu']])
6159
table.add_row(['memory', formatting.mb_to_gb(result['maxMemory'])])
62-
table.add_row(['public_ip',
63-
result['primaryIpAddress'] or formatting.blank()])
64-
table.add_row(['private_ip',
65-
result['primaryBackendIpAddress'] or formatting.blank()])
60+
table.add_row(['public_ip', result.get('primaryIpAddress', '-')])
61+
table.add_row(['private_ip', result.get('primaryBackendIpAddress', '-')])
6662
table.add_row(['private_only', result['privateNetworkOnlyFlag']])
6763
table.add_row(['private_cpu', result['dedicatedAccountHostOnlyFlag']])
6864
table.add_row(['created', result['createDate']])
6965
table.add_row(['modified', result['modifyDate']])
70-
if utils.lookup(result, 'billingItem') != []:
71-
table.add_row(['owner', formatting.FormattedItem(
72-
utils.lookup(result, 'billingItem', 'orderItem',
73-
'order', 'userRecord',
74-
'username') or formatting.blank(),
75-
)])
76-
else:
77-
table.add_row(['owner', formatting.blank()])
7866

79-
vlan_table = formatting.Table(['type', 'number', 'id'])
80-
for vlan in result['networkVlans']:
81-
vlan_table.add_row([
82-
vlan['networkSpace'], vlan['vlanNumber'], vlan['id']])
83-
table.add_row(['vlans', vlan_table])
67+
table.add_row(_get_owner_row(result))
68+
table.add_row(_get_vlan_table(result))
8469

85-
if result.get('networkComponents'):
86-
secgroup_table = formatting.Table(['interface', 'id', 'name'])
87-
has_secgroups = False
88-
for comp in result.get('networkComponents'):
89-
interface = 'PRIVATE' if comp['port'] == 0 else 'PUBLIC'
90-
for binding in comp['securityGroupBindings']:
91-
has_secgroups = True
92-
secgroup = binding['securityGroup']
93-
secgroup_table.add_row([
94-
interface, secgroup['id'],
95-
secgroup.get('name') or formatting.blank()])
96-
if has_secgroups:
97-
table.add_row(['security_groups', secgroup_table])
70+
bandwidth = vsi.get_bandwidth_allocation(vs_id)
71+
table.add_row(['Bandwidth', _bw_table(bandwidth)])
72+
73+
security_table = _get_security_table(result)
74+
if security_table is not None:
75+
table.add_row(['security_groups', security_table])
9876

99-
if result.get('notes'):
100-
table.add_row(['notes', result['notes']])
77+
table.add_row(['notes', result.get('notes', '-')])
10178

10279
if price:
10380
total_price = utils.lookup(result,
@@ -145,6 +122,20 @@ def cli(env, identifier, passwords=False, price=False):
145122
env.fout(table)
146123

147124

125+
def _bw_table(bw_data):
126+
"""Generates a bandwidth useage table"""
127+
table = formatting.Table(['Type', 'In GB', 'Out GB', 'Allotment'])
128+
for bw_point in bw_data.get('useage'):
129+
bw_type = 'Private'
130+
allotment = 'N/A'
131+
if bw_point['type']['alias'] == 'PUBLIC_SERVER_BW':
132+
bw_type = 'Public'
133+
allotment = bw_data['allotment'].get('amount', '-')
134+
135+
table.add_row([bw_type, bw_point['amountIn'], bw_point['amountOut'], allotment])
136+
return table
137+
138+
148139
def _cli_helper_dedicated_host(env, result, table):
149140
"""Get details on dedicated host for a virtual server."""
150141

@@ -160,3 +151,40 @@ def _cli_helper_dedicated_host(env, result, table):
160151
dedicated_host = {}
161152
table.add_row(['dedicated_host',
162153
dedicated_host.get('name') or formatting.blank()])
154+
155+
156+
def _get_owner_row(result):
157+
"""Formats and resturns the Owner row"""
158+
159+
if utils.lookup(result, 'billingItem') != []:
160+
owner = utils.lookup(result, 'billingItem', 'orderItem', 'order', 'userRecord', 'username')
161+
else:
162+
owner = formatting.blank()
163+
return(['owner', owner])
164+
165+
166+
def _get_vlan_table(result):
167+
"""Formats and resturns a vlan table"""
168+
169+
vlan_table = formatting.Table(['type', 'number', 'id'])
170+
for vlan in result['networkVlans']:
171+
vlan_table.add_row([
172+
vlan['networkSpace'], vlan['vlanNumber'], vlan['id']])
173+
return ['vlans', vlan_table]
174+
175+
176+
def _get_security_table(result):
177+
secgroup_table = formatting.Table(['interface', 'id', 'name'])
178+
has_secgroups = False
179+
180+
if result.get('networkComponents'):
181+
for comp in result.get('networkComponents'):
182+
interface = 'PRIVATE' if comp['port'] == 0 else 'PUBLIC'
183+
for binding in comp['securityGroupBindings']:
184+
has_secgroups = True
185+
secgroup = binding['securityGroup']
186+
secgroup_table.add_row([interface, secgroup['id'], secgroup.get('name', '-')])
187+
if has_secgroups:
188+
return secgroup_table
189+
else:
190+
return None

SoftLayer/CLI/virt/usage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
@click.option('--end_date', '-e', type=click.STRING, required=True, help="End Date e.g. 2019-4-2 (yyyy-MM-dd)")
1818
@click.option('--valid_type', '-t', type=click.STRING, required=True,
1919
help="Metric_Data_Type keyName e.g. CPU0, CPU1, MEMORY_USAGE, etc.")
20-
@click.option('--summary_period', '-p', type=click.INT, default=1800,
20+
@click.option('--summary_period', '-p', type=click.INT, default=3600,
2121
help="300, 600, 1800, 3600, 43200 or 86400 seconds")
2222
@environment.pass_env
2323
def cli(env, identifier, start_date, end_date, valid_type, summary_period):

SoftLayer/decoration.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
exceptions.ServerError,
1616
exceptions.ApplicationError,
1717
exceptions.RemoteSystemError,
18-
exceptions.TransportError
1918
)
2019

2120

0 commit comments

Comments
 (0)