Skip to content

Commit bee622e

Browse files
committed
Adds ability to list VLANs by name. Some refactoring of network manager.
1 parent 086889d commit bee622e

3 files changed

Lines changed: 109 additions & 113 deletions

File tree

SoftLayer/CLI/modules/vlan.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# :license: MIT, see LICENSE for more details.
1212

1313
from SoftLayer import NetworkManager
14-
from SoftLayer.CLI import CLIRunnable, Table, KeyValueTable
14+
from SoftLayer.CLI import CLIRunnable, Table, KeyValueTable, blank, resolve_id
1515

1616

1717
class VlanDetail(CLIRunnable):
@@ -29,7 +29,10 @@ class VlanDetail(CLIRunnable):
2929
def execute(self, args):
3030
mgr = NetworkManager(self.client)
3131

32-
vlan = mgr.get_vlan(args.get('<identifier>'))
32+
vlan_id = resolve_id(mgr.resolve_vlan_ids,
33+
args.get('<identifier>'),
34+
'VLAN')
35+
vlan = mgr.get_vlan(vlan_id)
3336

3437
t = KeyValueTable(['Name', 'Value'])
3538
t.align['Name'] = 'r'
@@ -98,29 +101,32 @@ class VlanList(CLIRunnable):
98101
hardware, ccis, networking
99102
100103
Filters:
101-
-d DC, --datacenter=DC datacenter shortname (sng01, dal05, ...)
102-
-n NUM, --number=NUM VLAN number
104+
-d DC, --datacenter=DC datacenter shortname (sng01, dal05, ...)
105+
-n NUM, --number=NUM VLAN number
106+
--name=NAME VLAN name
103107
"""
104108
action = 'list'
105109

106110
def execute(self, args):
107111
mgr = NetworkManager(self.client)
108112

109113
t = Table([
110-
'id', 'number', 'datacenter', 'IPs', 'hardware', 'ccis',
114+
'id', 'number', 'datacenter', 'name', 'IPs', 'hardware', 'ccis',
111115
'networking', 'firewall'
112116
])
113117
t.sortby = args.get('--sortby') or 'id'
114118

115119
vlans = mgr.list_vlans(
116120
datacenter=args.get('--datacenter'),
117-
vlan_number=args.get('--number')
121+
vlan_number=args.get('--number'),
122+
vlan_name=args.get('--name'),
118123
)
119124
for vlan in vlans:
120125
t.add_row([
121126
vlan['id'],
122127
vlan['vlanNumber'],
123128
vlan['primaryRouter']['datacenter']['name'],
129+
vlan.get('name') or blank(),
124130
vlan['totalPrimaryIpAddressCount'],
125131
len(vlan['hardware']),
126132
len(vlan['virtualGuests']),

SoftLayer/managers/network.py

Lines changed: 71 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
:license: MIT, see LICENSE for more details.
88
"""
99

10-
from SoftLayer.utils import (NestedDict, query_filter, IdentifierMixin,
11-
resolve_ids, lookup)
10+
from SoftLayer.utils import NestedDict, query_filter, resolve_ids, lookup
1211

1312

14-
class NetworkManager(IdentifierMixin, object):
13+
class NetworkManager(object):
1514
""" Manage Networks """
1615
def __init__(self, client):
1716
#: A valid `SoftLayer.API.Client` object that will be used for all
@@ -22,8 +21,6 @@ def __init__(self, client):
2221
#: Reference to the SoftLayer_Network_Vlan object.
2322
self.vlan = client['Network_Vlan']
2423
self.subnet = client['Network_Subnet']
25-
self.global_ip_resolvers = [self._get_global_ip_by_identifier]
26-
self.subnet_resolvers = [self._get_subnet_by_identifier]
2724

2825
def add_global_ip(self, version=4, test_order=False):
2926
""" Adds a global IP address to the account.
@@ -63,7 +60,7 @@ def add_subnet(self, subnet_type, quantity=None, vlan_id=None, version=4,
6360
# This means that we need to get all of the items and loop through them
6461
# looking for the items we need based upon the category, quantity, and
6562
# item description.
66-
for item in package.getItems(id=0, mask='mask[itemCategory]'):
63+
for item in package.getItems(id=0, mask='itemCategory'):
6764
category_code = lookup(item, 'itemCategory', 'categoryCode')
6865
if all([category_code == category,
6966
item.get('capacity') == quantity,
@@ -111,7 +108,7 @@ def cancel_global_ip(self, global_ip_id):
111108
:param int id: The ID of the global IP to be cancelled.
112109
"""
113110
service = self.client['Network_Subnet_IpAddress_Global']
114-
ip = service.getObject(id=global_ip_id, mask='mask[billingItem]')
111+
ip = service.getObject(id=global_ip_id, mask='billingItem')
115112
billing_id = ip['billingItem']['id']
116113

117114
billing_item = self.client['Billing_Item']
@@ -122,7 +119,7 @@ def cancel_subnet(self, subnet_id):
122119
123120
:param int subnet_id: The ID of the subnet to be cancelled.
124121
"""
125-
subnet = self.get_subnet(subnet_id, mask='mask[id, billingItem.id]')
122+
subnet = self.get_subnet(subnet_id, mask='id, billingItem.id')
126123
billing_id = subnet['billingItem']['id']
127124

128125
billing_item = self.client['Billing_Item']
@@ -133,30 +130,21 @@ def edit_rwhois(self, abuse_email=None, address1=None, address2=None,
133130
first_name=None, last_name=None, postal_code=None,
134131
private_residence=None, state=None):
135132
update = {}
136-
137-
if abuse_email is not None:
138-
update['abuseEmail'] = abuse_email
139-
if address1 is not None:
140-
update['address1'] = address1
141-
if address2 is not None:
142-
update['address2'] = address2
143-
if city is not None:
144-
update['city'] = city
145-
if company_name is not None:
146-
update['companyName'] = company_name
147-
if country is not None:
148-
update['country'] = country
149-
if first_name is not None:
150-
update['firstName'] = first_name
151-
if last_name is not None:
152-
update['lastName'] = last_name
153-
if postal_code is not None:
154-
update['postalCode'] = postal_code
155-
if private_residence is not None:
156-
update['privateResidenceFlag'] = private_residence
157-
if state is not None:
158-
update['state'] = state
159-
133+
for key, value in [('abuseEmail', abuse_email),
134+
('address1', address1),
135+
('address2', address2),
136+
('city', city),
137+
('companyName', company_name),
138+
('country', country),
139+
('firstName', first_name),
140+
('lastName', last_name),
141+
('privateResidenceFlag', private_residence),
142+
('state', state),
143+
('postalCode', postal_code)]:
144+
if key is not None:
145+
update[key] = value
146+
147+
# If there's anything to update, update it
160148
if update:
161149
rwhois = self.get_rwhois()
162150
self.client['Network_Subnet_Rwhois_Data'].editObject(
@@ -169,13 +157,8 @@ def ip_lookup(self, ip):
169157
:returns: A dictionary of information about the IP
170158
171159
"""
172-
mask = [
173-
'hardware',
174-
'virtualGuest'
175-
]
176-
mask = 'mask[%s]' % ','.join(mask)
177160
obj = self.client['Network_Subnet_IpAddress']
178-
return obj.getByIpAddress(ip, mask=mask)
161+
return obj.getByIpAddress(ip, mask='hardware, virtualGuest')
179162

180163
def get_rwhois(self):
181164
""" Returns the RWhois information about the current account.
@@ -192,7 +175,7 @@ def get_subnet(self, subnet_id, **kwargs):
192175
:returns: A dictionary of information about the subnet
193176
"""
194177
if 'mask' not in kwargs:
195-
kwargs['mask'] = 'mask[%s]' % ','.join(self._get_subnet_mask())
178+
kwargs['mask'] = ','.join(self._get_subnet_mask())
196179

197180
return self.subnet.getObject(id=subnet_id, **kwargs)
198181

@@ -206,19 +189,30 @@ def get_vlan(self, vlan_id):
206189
"""
207190
return self.vlan.getObject(id=vlan_id, mask=self._get_vlan_mask())
208191

209-
def list_global_ips(self, version=0):
192+
def list_global_ips(self, version=None, identifier=None, **kwargs):
210193
""" Returns a list of all global IP address records on the account.
211194
212-
:param int version: Only returns IPs of this version (4 or 6).
195+
:param int version: Only returns IPs of this version (4 or 6)
196+
:param string identifier: If specified, the list will only contain the
197+
global ips matching this network identifier.
213198
"""
214-
mask = ['destinationIpAddress[hardware, virtualGuest]', 'ipAddress']
215-
mask = 'mask[%s]' % ','.join(mask)
199+
if 'mask' not in kwargs:
200+
mask = ['destinationIpAddress[hardware, virtualGuest]',
201+
'ipAddress']
202+
kwargs['mask'] = ','.join(mask)
203+
216204
_filter = NestedDict({})
205+
217206
if version:
218207
v = query_filter(version)
219208
_filter['globalIpRecords']['ipAddress']['subnet']['version'] = v
220-
_filter = _filter.to_dict()
221-
return self.account.getGlobalIpRecords(filter=_filter, mask=mask)
209+
210+
if identifier:
211+
subnet_filter = _filter['globalIpRecords']['ipAddress']['subnet']
212+
subnet_filter['networkIdentifier'] = query_filter(identifier)
213+
214+
kwargs['filter'] = _filter.to_dict()
215+
return self.account.getGlobalIpRecords(**kwargs)
222216

223217
def list_subnets(self, identifier=None, datacenter=None, version=0,
224218
subnet_type=None, **kwargs):
@@ -238,8 +232,7 @@ def list_subnets(self, identifier=None, datacenter=None, version=0,
238232
239233
"""
240234
if 'mask' not in kwargs:
241-
mask = self._get_subnet_mask()
242-
kwargs['mask'] = 'mask[%s]' % ','.join(mask)
235+
kwargs['mask'] = ','.join(self._get_subnet_mask())
243236

244237
_filter = NestedDict(kwargs.get('filter') or {})
245238

@@ -254,21 +247,14 @@ def list_subnets(self, identifier=None, datacenter=None, version=0,
254247
_filter['subnets']['subnetType'] = query_filter(subnet_type)
255248
else:
256249
# This filters out global IPs from the subnet listing.
257-
_filter['subnets']['subnetType'] = {'operation': 'not null'}
250+
_filter['subnets']['subnetType'] = {'operation': '!= GLOBAL_IP'}
258251

259252
kwargs['filter'] = _filter.to_dict()
260253

261-
results = []
262-
263-
# Filtering out routed global IPs here. This is being done in code
264-
# because of complications getting the object filter syntax working.
265-
for subnet in self.account.getSubnets(**kwargs):
266-
if 'GLOBAL_IP' not in subnet['subnetType']:
267-
results.append(subnet)
254+
return self.account.getSubnets(**kwargs)
268255

269-
return results
270-
271-
def list_vlans(self, datacenter=None, vlan_number=None, **kwargs):
256+
def list_vlans(self, datacenter=None, vlan_number=None, vlan_name=None,
257+
**kwargs):
272258
""" Display a list of all VLANs on the account.
273259
274260
This provides a quick overview of all VLANs including information about
@@ -278,6 +264,8 @@ def list_vlans(self, datacenter=None, vlan_number=None, **kwargs):
278264
VLANs in the specified data center.
279265
:param int vlan_number: If specified, the list will only contain the
280266
VLAN matching this VLAN number.
267+
:param int vlan_name: If specified, the list will only contain the
268+
VLAN matching this VLAN name.
281269
:param dict \*\*kwargs: response-level arguments (limit, offset, etc.)
282270
283271
"""
@@ -286,25 +274,28 @@ def list_vlans(self, datacenter=None, vlan_number=None, **kwargs):
286274
if vlan_number:
287275
_filter['networkVlans']['vlanNumber'] = query_filter(vlan_number)
288276

277+
if vlan_name:
278+
_filter['networkVlans']['name'] = query_filter(vlan_name)
279+
289280
if datacenter:
290281
_filter['networkVlans']['primaryRouter']['datacenter']['name'] = \
291282
query_filter(datacenter)
292283

293284
kwargs['filter'] = _filter.to_dict()
294285

295-
return self._get_vlans(**kwargs)
286+
if 'mask' not in kwargs:
287+
kwargs['mask'] = self._get_vlan_mask()
296288

297-
def resolve_global_ip_ids(self, identifier):
298-
results = resolve_ids(identifier, self.global_ip_resolvers)
289+
return self.account.getNetworkVlans(**kwargs)
299290

300-
if results:
301-
return results[0]
291+
def resolve_global_ip_ids(self, identifier):
292+
return resolve_ids(identifier, [self._list_global_ips_by_identifier])
302293

303294
def resolve_subnet_ids(self, identifier):
304-
results = resolve_ids(identifier, self.subnet_resolvers)
295+
return resolve_ids(identifier, [self._list_subnets_by_identifier])
305296

306-
if results:
307-
return results[0]
297+
def resolve_vlan_ids(self, identifier):
298+
return resolve_ids(identifier, [self._list_vlans_by_name])
308299

309300
def summary_by_datacenter(self):
310301
""" Provides a dictionary with a summary of all network information on
@@ -324,7 +315,7 @@ def summary_by_datacenter(self):
324315
unique_servers = []
325316
unique_network = []
326317

327-
for vlan in self._get_vlans():
318+
for vlan in self.list_vlans():
328319
dc = vlan['primaryRouter']['datacenter']
329320
name = dc['name']
330321
if name not in datacenters:
@@ -368,41 +359,31 @@ def unassign_global_ip(self, global_ip_id):
368359
return self.client['Network_Subnet_IpAddress_Global'].unroute(
369360
id=global_ip_id)
370361

371-
def _get_global_ip_by_identifier(self, identifier):
372-
""" Returns the ID of the global IP matching the specified identifier.
362+
def _list_global_ips_by_identifier(self, identifier):
363+
""" Returns a list of IDs of the global IP matching the specified
364+
network identifier
373365
374366
:param string identifier: The identifier to look up
375367
:returns: The ID of the matching subnet or None
376368
"""
377-
results = []
378-
for ip in self.list_global_ips():
379-
if ip['ipAddress']['subnet']['networkIdentifier'] == identifier:
380-
results.append(ip['id'])
381-
return results
369+
results = self.list_global_ips(identifier=identifier, mask='id')
370+
return [result['id'] for result in results]
382371

383-
def _get_subnet_by_identifier(self, identifier):
384-
""" Returns the ID of the subnet matching the specified identifier.
372+
def _list_subnets_by_identifier(self, identifier):
373+
""" Returns a list of IDs of the subnet matching the specified
374+
network identifier
385375
386376
:param string identifier: The identifier to look up
387377
:returns: The ID of the matching subnet or None
388378
"""
389-
390379
identifier = identifier.split('/', 1)[0]
391380

392-
results = self.list_subnets(identifier=identifier,
393-
mask='id,subnetType')
381+
results = self.list_subnets(identifier=identifier, mask='id')
394382
return [result['id'] for result in results]
395383

396-
def _get_vlans(self, **kwargs):
397-
""" Returns a list of VLANs.
398-
399-
Wrapper method for preventing duplicated code.
400-
401-
:param dict \*\*kwargs: response-level arguments (limit, offset, etc.)
402-
403-
"""
404-
return self.account.getNetworkVlans(mask=self._get_vlan_mask(),
405-
**kwargs)
384+
def _list_vlans_by_name(self, name):
385+
results = self.list_vlans(vlan_name=name, mask='id')
386+
return [result['id'] for result in results]
406387

407388
def _get_subnet_mask(self):
408389
""" Returns the standard subnet object mask.
@@ -433,4 +414,4 @@ def _get_vlan_mask(self):
433414
'virtualGuests',
434415
]
435416

436-
return 'mask[%s]' % ','.join(mask)
417+
return ','.join(mask)

0 commit comments

Comments
 (0)