From 6ccdcbd7fe2ed28af89a13e7b074650908184209 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 10 Jul 2019 16:49:28 -0500 Subject: [PATCH 01/23] removed legacy LB commands, added LBaaS and Netscaler support --- SoftLayer/CLI/loadbal/__init__.py | 10 -- SoftLayer/CLI/loadbal/cancel.py | 29 ----- SoftLayer/CLI/loadbal/create.py | 25 ---- SoftLayer/CLI/loadbal/create_options.py | 35 ----- SoftLayer/CLI/loadbal/detail.py | 157 ++++++++++++++--------- SoftLayer/CLI/loadbal/group_add.py | 41 ------ SoftLayer/CLI/loadbal/group_delete.py | 28 ---- SoftLayer/CLI/loadbal/group_edit.py | 43 ------- SoftLayer/CLI/loadbal/group_reset.py | 21 --- SoftLayer/CLI/loadbal/health.py | 20 +++ SoftLayer/CLI/loadbal/health_checks.py | 26 ---- SoftLayer/CLI/loadbal/list.py | 74 ++++++----- SoftLayer/CLI/loadbal/ns_detail.py | 49 +++++++ SoftLayer/CLI/loadbal/ns_list.py | 46 +++++++ SoftLayer/CLI/loadbal/routing_methods.py | 25 ---- SoftLayer/CLI/loadbal/routing_types.py | 24 ---- SoftLayer/CLI/loadbal/service_add.py | 53 -------- SoftLayer/CLI/loadbal/service_delete.py | 28 ---- SoftLayer/CLI/loadbal/service_edit.py | 52 -------- SoftLayer/CLI/loadbal/service_toggle.py | 28 ---- SoftLayer/CLI/routes.py | 19 +-- SoftLayer/managers/load_balancer.py | 61 +++++++-- SoftLayer/utils.py | 2 + 23 files changed, 311 insertions(+), 585 deletions(-) delete mode 100644 SoftLayer/CLI/loadbal/cancel.py delete mode 100644 SoftLayer/CLI/loadbal/create.py delete mode 100644 SoftLayer/CLI/loadbal/create_options.py delete mode 100644 SoftLayer/CLI/loadbal/group_add.py delete mode 100644 SoftLayer/CLI/loadbal/group_delete.py delete mode 100644 SoftLayer/CLI/loadbal/group_edit.py delete mode 100644 SoftLayer/CLI/loadbal/group_reset.py create mode 100644 SoftLayer/CLI/loadbal/health.py delete mode 100644 SoftLayer/CLI/loadbal/health_checks.py create mode 100644 SoftLayer/CLI/loadbal/ns_detail.py create mode 100644 SoftLayer/CLI/loadbal/ns_list.py delete mode 100644 SoftLayer/CLI/loadbal/routing_methods.py delete mode 100644 SoftLayer/CLI/loadbal/routing_types.py delete mode 100644 SoftLayer/CLI/loadbal/service_add.py delete mode 100644 SoftLayer/CLI/loadbal/service_delete.py delete mode 100644 SoftLayer/CLI/loadbal/service_edit.py delete mode 100644 SoftLayer/CLI/loadbal/service_toggle.py diff --git a/SoftLayer/CLI/loadbal/__init__.py b/SoftLayer/CLI/loadbal/__init__.py index 8f7becb62..77d12e33d 100644 --- a/SoftLayer/CLI/loadbal/__init__.py +++ b/SoftLayer/CLI/loadbal/__init__.py @@ -1,12 +1,2 @@ """Load balancers.""" -from SoftLayer.CLI import exceptions - - -def parse_id(input_id): - """Parse the load balancer kind and actual id from the "kind:id" form.""" - parts = input_id.split(':') - if len(parts) != 2: - raise exceptions.CLIAbort( - 'Invalid ID %s: ID should be of the form "kind:id"' % input_id) - return parts[0], int(parts[1]) diff --git a/SoftLayer/CLI/loadbal/cancel.py b/SoftLayer/CLI/loadbal/cancel.py deleted file mode 100644 index 68e3e62ca..000000000 --- a/SoftLayer/CLI/loadbal/cancel.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Cancel an existing load balancer.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions -from SoftLayer.CLI import formatting -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@environment.pass_env -def cli(env, identifier): - """Cancel an existing load balancer.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - - _, loadbal_id = loadbal.parse_id(identifier) - - if not (env.skip_confirmations or - formatting.confirm("This action will cancel a load balancer. " - "Continue?")): - raise exceptions.CLIAbort('Aborted.') - - mgr.cancel_lb(loadbal_id) - env.fout('Load Balancer with id %s is being cancelled!' % identifier) diff --git a/SoftLayer/CLI/loadbal/create.py b/SoftLayer/CLI/loadbal/create.py deleted file mode 100644 index e32cc6297..000000000 --- a/SoftLayer/CLI/loadbal/create.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Adds a load balancer given the id returned from create-options.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions -from SoftLayer.CLI import formatting - - -@click.command() -@click.argument('billing-id') -@click.option('--datacenter', '-d', - help='Datacenter shortname (sng01, dal05, ...)') -@environment.pass_env -def cli(env, billing_id, datacenter): - """Adds a load balancer given the id returned from create-options.""" - mgr = SoftLayer.LoadBalancerManager(env.client) - - if not formatting.confirm("This action will incur charges on your " - "account. Continue?"): - raise exceptions.CLIAbort('Aborted.') - mgr.add_local_lb(billing_id, datacenter=datacenter) - env.fout("Load balancer is being created!") diff --git a/SoftLayer/CLI/loadbal/create_options.py b/SoftLayer/CLI/loadbal/create_options.py deleted file mode 100644 index b4392b109..000000000 --- a/SoftLayer/CLI/loadbal/create_options.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Show load balancer options.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import formatting - - -@click.command() -@environment.pass_env -def cli(env): - """Get price options to create a load balancer with.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - - table = formatting.Table(['price_id', 'capacity', 'description', 'price']) - - table.sortby = 'price' - table.align['price'] = 'r' - table.align['capacity'] = 'r' - table.align['id'] = 'r' - - packages = mgr.get_lb_pkgs() - - for package in packages: - table.add_row([ - package['prices'][0]['id'], - package.get('capacity'), - package['description'], - '%.2f' % float(package['prices'][0]['recurringFee']) - ]) - - env.fout(table) diff --git a/SoftLayer/CLI/loadbal/detail.py b/SoftLayer/CLI/loadbal/detail.py index c8711fbf5..6f29e7655 100644 --- a/SoftLayer/CLI/loadbal/detail.py +++ b/SoftLayer/CLI/loadbal/detail.py @@ -1,81 +1,122 @@ -"""Get Load balancer details.""" -# :license: MIT, see LICENSE for more details. - +"""Get Load Balancer as a Service details.""" import click import SoftLayer from SoftLayer.CLI import environment from SoftLayer.CLI import formatting -from SoftLayer.CLI import loadbal - +from SoftLayer import utils +from pprint import pprint as pp @click.command() @click.argument('identifier') @environment.pass_env def cli(env, identifier): - """Get Load balancer details.""" + """Get Load Balancer as a Service details.""" mgr = SoftLayer.LoadBalancerManager(env.client) - _, loadbal_id = loadbal.parse_id(identifier) + lb = mgr.get_lb(identifier) + pp(lb) + table = lbaas_table(lb) + + env.fout(table) - load_balancer = mgr.get_local_lb(loadbal_id) +def lbaas_table(lb): + """Generates a table from a list of LBaaS devices""" table = formatting.KeyValueTable(['name', 'value']) - table.align['name'] = 'l' + table.align['name'] = 'r' table.align['value'] = 'l' - table.add_row(['ID', 'local:%s' % load_balancer['id']]) - table.add_row(['IP Address', load_balancer['ipAddress']['ipAddress']]) - name = load_balancer['loadBalancerHardware'][0]['datacenter']['name'] - table.add_row(['Datacenter', name]) - table.add_row(['Connections limit', load_balancer['connectionLimit']]) - table.add_row(['Dedicated', load_balancer['dedicatedFlag']]) - table.add_row(['HA', load_balancer['highAvailabilityFlag']]) - table.add_row(['SSL Enabled', load_balancer['sslEnabledFlag']]) - table.add_row(['SSL Active', load_balancer['sslActiveFlag']]) + table.add_row(['Id', lb.get('id')]) + table.add_row(['UUI', lb.get('uuid')]) + table.add_row(['Address', lb.get('address')]) + table.add_row(['Location', utils.lookup(lb, 'datacenter', 'longName')]) + table.add_row(['Description', lb.get('description')]) + table.add_row(['Name', lb.get('name')]) + table.add_row(['Status', "{} / {}".format(lb.get('provisioningStatus'), lb.get('operatingStatus'))]) - index0 = 1 - for virtual_server in load_balancer['virtualServers']: - for group in virtual_server['serviceGroups']: - service_group_table = formatting.KeyValueTable(['name', 'value']) + # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_HealthMonitor/ + hp_table = formatting.Table(['UUID', 'Interval', 'Retries', 'Type', 'Timeout', 'Modify', 'Active']) + for hp in lb.get('healthMonitors', []): + hp_table.add_row([ + hp.get('uuid'), + hp.get('interval'), + hp.get('maxRetries'), + hp.get('monitorType'), + hp.get('timeout'), + utils.clean_time(hp.get('modifyDate')), + hp.get('provisioningStatus') + ]) + table.add_row(['Checks', hp_table]) - table.add_row(['Service Group %s' % index0, service_group_table]) - index0 += 1 + # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7Pool/ + l7_table = formatting.Table(['UUID', 'Balancer', 'Name', 'Protocol', 'Modify', 'Active' ]) + for l7 in lb.get('l7Pools', []): + l7_table.add_row([ + l7.get('uuid'), + l7.get('loadBalancingAlgorithm'), + l7.get('name'), + l7.get('protocol'), + utils.clean_time(l7.get('modifyDate')), + l7.get('provisioningStatus') + ]) + table.add_row(['L7 Pools', l7_table]) - service_group_table.add_row(['Guest ID', - virtual_server['id']]) - service_group_table.add_row(['Port', virtual_server['port']]) - service_group_table.add_row(['Allocation', - '%s %%' % - virtual_server['allocation']]) - service_group_table.add_row(['Routing Type', - '%s:%s' % - (group['routingTypeId'], - group['routingType']['name'])]) - service_group_table.add_row(['Routing Method', - '%s:%s' % - (group['routingMethodId'], - group['routingMethod']['name'])]) + pools = {} + # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Listener/ + listener_table = formatting.Table(['UUID', 'Max Connection', 'Mapping', 'Balancer', 'Modify', 'Active']) + for listener in lb.get('listeners', []): + pool = listener.get('defaultPool') + priv_map = "{}:{}".format(pool['protocol'], pool['protocolPort']) + pools[pool['uuid']] = priv_map + mapping = "{}:{} -> {}".format(listener.get('protocol'), listener.get('protocolPort'), priv_map) + pool_table = formatting.Table(['Address', ]) + listener_table.add_row([ + listener.get('uuid'), + listener.get('connectionLimit', 'None'), + mapping, + pool.get('loadBalancingAlgorithm', 'None'), + utils.clean_time(listener.get('modifyDate')), + listener.get('provisioningStatus') + ]) + table.add_row(['Pools', listener_table]) - index1 = 1 - for service in group['services']: - service_table = formatting.KeyValueTable(['name', 'value']) + # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Member/ + member_col = ['UUID', 'Address', 'Weight', 'Modify', 'Active'] + for uuid in pools.keys(): + member_col.append(pools[uuid]) + member_table = formatting.Table(member_col) + for member in lb.get('members', []): + row = [ + member.get('uuid'), + member.get('address'), + member.get('weight'), + utils.clean_time(member.get('modifyDate')), + member.get('provisioningStatus') + ] + for uuid in pools.keys(): + row.append(getMemberHp(lb.get('health'), member.get('uuid'), uuid)) + member_table.add_row(row) + table.add_row(['Members',member_table]) - service_group_table.add_row(['Service %s' % index1, - service_table]) - index1 += 1 + # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_SSLCipher/ + ssl_table = formatting.Table(['Id', 'Name']) + for ssl in lb.get('sslCiphers', []): + ssl_table.add_row([ssl.get('id'), ssl.get('name')]) + table.add_row(['Ciphers', ssl_table]) + return table - health_check = service['healthChecks'][0] - service_table.add_row(['Service ID', service['id']]) - service_table.add_row(['IP Address', - service['ipAddress']['ipAddress']]) - service_table.add_row(['Port', service['port']]) - service_table.add_row(['Health Check', - '%s:%s' % - (health_check['healthCheckTypeId'], - health_check['type']['name'])]) - service_table.add_row( - ['Weight', service['groupReferences'][0]['weight']]) - service_table.add_row(['Enabled', service['enabled']]) - service_table.add_row(['Status', service['status']]) +def getMemberHp(checks, member_uuid, pool_uuid): + """Helper function to find a members health in a given pool - env.fout(table) + :param checks list: https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Pool/#healthMonitor + :param member_uuid: server UUID we are looking for + :param pool_uuid: Connection pool uuid to search for + """ + status = "---" + for check in checks: + if check.get('poolUuid') == pool_uuid: + for hp_member in check.get('membersHealth'): + if hp_member.get('uuid') == member_uuid: + status = hp_member.get('status') + + return status \ No newline at end of file diff --git a/SoftLayer/CLI/loadbal/group_add.py b/SoftLayer/CLI/loadbal/group_add.py deleted file mode 100644 index 202c6cab9..000000000 --- a/SoftLayer/CLI/loadbal/group_add.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Adds a new load_balancer service.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@click.option('--allocation', - required=True, - type=click.INT, - help="The allocated percent of connections") -@click.option('--port', - required=True, - help="The port number", - type=click.INT) -@click.option('--routing-type', - required=True, - help="The port routing type") -@click.option('--routing-method', - required=True, - help="The routing method") -@environment.pass_env -def cli(env, identifier, allocation, port, routing_type, routing_method): - """Adds a new load_balancer service.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - - _, loadbal_id = loadbal.parse_id(identifier) - - mgr.add_service_group(loadbal_id, - allocation=allocation, - port=port, - routing_type=routing_type, - routing_method=routing_method) - - env.fout('Load balancer service group is being added!') diff --git a/SoftLayer/CLI/loadbal/group_delete.py b/SoftLayer/CLI/loadbal/group_delete.py deleted file mode 100644 index 74980b7bd..000000000 --- a/SoftLayer/CLI/loadbal/group_delete.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Deletes an existing load balancer service group.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions -from SoftLayer.CLI import formatting -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@environment.pass_env -def cli(env, identifier): - """Deletes an existing load balancer service group.""" - mgr = SoftLayer.LoadBalancerManager(env.client) - - _, group_id = loadbal.parse_id(identifier) - - if not (env.skip_confirmations or - formatting.confirm("This action will cancel a service group. " - "Continue?")): - raise exceptions.CLIAbort('Aborted.') - - mgr.delete_service_group(group_id) - env.fout('Service group %s is being deleted!' % identifier) diff --git a/SoftLayer/CLI/loadbal/group_edit.py b/SoftLayer/CLI/loadbal/group_edit.py deleted file mode 100644 index c7ed92c87..000000000 --- a/SoftLayer/CLI/loadbal/group_edit.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Edit an existing load balancer service group.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@click.option('--allocation', - type=click.INT, - help="Change the allocated percent of connections") -@click.option('--port', - help="Change the port number", - type=click.INT) -@click.option('--routing-type', - help="Change the port routing type") -@click.option('--routing-method', - help="Change the routing method") -@environment.pass_env -def cli(env, identifier, allocation, port, routing_type, routing_method): - """Edit an existing load balancer service group.""" - mgr = SoftLayer.LoadBalancerManager(env.client) - - loadbal_id, group_id = loadbal.parse_id(identifier) - - # check if any input is provided - if not any([allocation, port, routing_type, routing_method]): - raise exceptions.CLIAbort( - 'At least one property is required to be changed!') - - mgr.edit_service_group(loadbal_id, - group_id, - allocation=allocation, - port=port, - routing_type=routing_type, - routing_method=routing_method) - - env.fout('Load balancer service group %s is being updated!' % identifier) diff --git a/SoftLayer/CLI/loadbal/group_reset.py b/SoftLayer/CLI/loadbal/group_reset.py deleted file mode 100644 index 093230633..000000000 --- a/SoftLayer/CLI/loadbal/group_reset.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Reset connections on a certain service group.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@environment.pass_env -def cli(env, identifier): - """Reset connections on a certain service group.""" - mgr = SoftLayer.LoadBalancerManager(env.client) - - loadbal_id, group_id = loadbal.parse_id(identifier) - - mgr.reset_service_group(loadbal_id, group_id) - env.fout('Load balancer service group connections are being reset!') diff --git a/SoftLayer/CLI/loadbal/health.py b/SoftLayer/CLI/loadbal/health.py new file mode 100644 index 000000000..d101b9b30 --- /dev/null +++ b/SoftLayer/CLI/loadbal/health.py @@ -0,0 +1,20 @@ +"""Manage LBaaS health checks.""" +import click + +import SoftLayer +from SoftLayer.CLI import environment +from SoftLayer.CLI import formatting +from SoftLayer import utils +from pprint import pprint as pp + +@click.command() +@click.argument('identifier') +@environment.pass_env +def cli(env, identifier): + """Manage LBaaS health checks.""" + mgr = SoftLayer.LoadBalancerManager(env.client) + + lb = mgr.get_lb(identifier) + table = lbaas_table(lb) + + env.fout(table) diff --git a/SoftLayer/CLI/loadbal/health_checks.py b/SoftLayer/CLI/loadbal/health_checks.py deleted file mode 100644 index 49a12a5cd..000000000 --- a/SoftLayer/CLI/loadbal/health_checks.py +++ /dev/null @@ -1,26 +0,0 @@ -"""List health check types.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import formatting - - -@click.command() -@environment.pass_env -def cli(env): - """List health check types.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - - hc_types = mgr.get_hc_types() - table = formatting.KeyValueTable(['ID', 'Name']) - table.align['ID'] = 'l' - table.align['Name'] = 'l' - table.sortby = 'ID' - for hc_type in hc_types: - table.add_row([hc_type['id'], hc_type['name']]) - - env.fout(table) diff --git a/SoftLayer/CLI/loadbal/list.py b/SoftLayer/CLI/loadbal/list.py index df44cc33e..e8394170c 100644 --- a/SoftLayer/CLI/loadbal/list.py +++ b/SoftLayer/CLI/loadbal/list.py @@ -1,49 +1,53 @@ -"""List active load balancers.""" -# :license: MIT, see LICENSE for more details. - +"""List active Load Balancer as a Service devices.""" import click import SoftLayer from SoftLayer.CLI import environment from SoftLayer.CLI import formatting - +from SoftLayer import utils +from pprint import pprint as pp @click.command() @environment.pass_env def cli(env): - """List active load balancers.""" + """List active Load Balancer as a Service devices.""" mgr = SoftLayer.LoadBalancerManager(env.client) - load_balancers = mgr.get_local_lbs() - - table = formatting.Table(['ID', - 'VIP Address', - 'Location', - 'SSL Offload', - 'Connections/second', - 'Type']) - - table.align['Connections/second'] = 'r' - - for load_balancer in load_balancers: - ssl_support = 'Not Supported' - if load_balancer['sslEnabledFlag']: - if load_balancer['sslActiveFlag']: - ssl_support = 'On' - else: - ssl_support = 'Off' - lb_type = 'Standard' - if load_balancer['dedicatedFlag']: - lb_type = 'Dedicated' - elif load_balancer['highAvailabilityFlag']: - lb_type = 'HA' + lbaas = mgr.get_lbaas() + if lbaas: + lbaas_table = generate_lbaas_table(lbaas) + env.fout(lbaas_table) + + else: + env.fout("No LBaaS devices found") + + +def location_sort(x): + """Quick function that just returns the datacenter longName for sorting""" + return utils.lookup(x, 'datacenter', 'longName') + + +def generate_lbaas_table(lbaas): + """Takes a list of SoftLayer_Network_LBaaS_LoadBalancer and makes a table""" + table = formatting.Table([ + 'Id', 'Location', 'Address', 'Description', 'Public', 'Create Date', 'Members', 'Listeners' + ], title="IBM Cloud LoadBalancer") + + table.align['Address'] = 'l' + table.align['Description'] = 'l' + table.align['Location'] = 'l' + for lb in sorted(lbaas,key=location_sort): table.add_row([ - 'local:%s' % load_balancer['id'], - load_balancer['ipAddress']['ipAddress'], - load_balancer['loadBalancerHardware'][0]['datacenter']['name'], - ssl_support, - load_balancer['connectionLimit'], - lb_type + lb.get('id'), + utils.lookup(lb, 'datacenter', 'longName'), + lb.get('address'), + lb.get('description'), + 'Yes' if lb.get('isPublic', 1) == 1 else 'No', + utils.clean_time(lb.get('createDate')), + lb.get('memberCount', 0), + lb.get('listenerCount', 0) + + ]) + return table - env.fout(table) diff --git a/SoftLayer/CLI/loadbal/ns_detail.py b/SoftLayer/CLI/loadbal/ns_detail.py new file mode 100644 index 000000000..976983b62 --- /dev/null +++ b/SoftLayer/CLI/loadbal/ns_detail.py @@ -0,0 +1,49 @@ +"""Get Netscaler details.""" +import click + +import SoftLayer +from SoftLayer.CLI import environment +from SoftLayer.CLI import formatting +from SoftLayer import utils + + +@click.command() +@click.argument('identifier') +@environment.pass_env +def cli(env, identifier): + """Get Netscaler details.""" + mgr = SoftLayer.LoadBalancerManager(env.client) + + lb = mgr.get_adc(identifier) + table = netscaler_table(lb) + env.fout(table) + + +def netscaler_table(lb): + table = formatting.KeyValueTable(['name', 'value']) + table.align['name'] = 'r' + table.align['value'] = 'l' + table.add_row(['Id', lb.get('id')]) + table.add_row(['Type', lb.get('description')]) + table.add_row(['Name', lb.get('name')]) + table.add_row(['Location', utils.lookup(lb, 'datacenter', 'longName')]) + table.add_row(['Managment Ip', lb.get('managementIpAddress')]) + table.add_row(['Root Password', utils.lookup(lb, 'password', 'password')]) + table.add_row(['Primary Ip', lb.get('primaryIpAddress')]) + table.add_row(['License Expiration', utils.clean_time(lb.get('licenseExpirationDate'))]) + subnet_table = formatting.Table(['Id', 'Subnet', 'Type', 'Space']) + for subnet in lb.get('subnets', []): + subnet_table.add_row([ + subnet.get('id'), + "{}/{}".format(subnet.get('networkIdentifier'), subnet.get('cidr')), + subnet.get('subnetType'), + subnet.get('addressSpace') + ]) + table.add_row(['Subnets', subnet_table]) + + vlan_table = formatting.Table(['Id', 'Number']) + for vlan in lb.get('networkVlans', []): + vlan_table.add_row([vlan.get('id'), vlan.get('vlanNumber')]) + table.add_row(['Vlans', vlan_table]) + + return table diff --git a/SoftLayer/CLI/loadbal/ns_list.py b/SoftLayer/CLI/loadbal/ns_list.py new file mode 100644 index 000000000..dd97a2f7e --- /dev/null +++ b/SoftLayer/CLI/loadbal/ns_list.py @@ -0,0 +1,46 @@ +"""List active Netscaler devices.""" +import click + +import SoftLayer +from SoftLayer.CLI import environment +from SoftLayer.CLI import formatting +from SoftLayer import utils + + +@click.command() +@environment.pass_env +def cli(env): + """List active Netscaler devices.""" + mgr = SoftLayer.LoadBalancerManager(env.client) + + netscalers = mgr.get_adcs() + if netscalers: + adc_table = generate_netscaler_table(netscalers) + env.fout(adc_table) + else: + env.fout("No Netscalers") + + +def location_sort(x): + """Quick function that just returns the datacenter longName for sorting""" + return utils.lookup(x, 'datacenter', 'longName') + +def generate_netscaler_table(netscalers): + """Tales a list of SoftLayer_Network_Application_Delivery_Controller and makes a table""" + table = formatting.Table([ + 'Id', 'Location', 'Name', 'Description', 'IP Address', 'Management Ip', 'Bandwidth', 'Create Date' + ], title="Netscalers") + for adc in sorted(netscalers, key=location_sort): + table.add_row([ + adc.get('id'), + utils.lookup(adc, 'datacenter', 'longName'), + adc.get('name'), + adc.get('description'), + adc.get('primaryIpAddress'), + adc.get('managementIpAddress'), + adc.get('outboundPublicBandwidthUsage',0), + utils.clean_time(adc.get('createDate')) + ]) + return table + + diff --git a/SoftLayer/CLI/loadbal/routing_methods.py b/SoftLayer/CLI/loadbal/routing_methods.py deleted file mode 100644 index 3ecb9c3e9..000000000 --- a/SoftLayer/CLI/loadbal/routing_methods.py +++ /dev/null @@ -1,25 +0,0 @@ -"""List routing methods.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import formatting - - -@click.command() -@environment.pass_env -def cli(env): - """List routing types.""" - mgr = SoftLayer.LoadBalancerManager(env.client) - - routing_methods = mgr.get_routing_methods() - table = formatting.KeyValueTable(['ID', 'Name']) - table.align['ID'] = 'l' - table.align['Name'] = 'l' - table.sortby = 'ID' - for routing_method in routing_methods: - table.add_row([routing_method['id'], routing_method['name']]) - - env.fout(table) diff --git a/SoftLayer/CLI/loadbal/routing_types.py b/SoftLayer/CLI/loadbal/routing_types.py deleted file mode 100644 index 88e8b8c3b..000000000 --- a/SoftLayer/CLI/loadbal/routing_types.py +++ /dev/null @@ -1,24 +0,0 @@ -"""List routing types.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import formatting - - -@click.command() -@environment.pass_env -def cli(env): - """List routing types.""" - mgr = SoftLayer.LoadBalancerManager(env.client) - - routing_types = mgr.get_routing_types() - table = formatting.KeyValueTable(['ID', 'Name']) - table.align['ID'] = 'l' - table.align['Name'] = 'l' - table.sortby = 'ID' - for routing_type in routing_types: - table.add_row([routing_type['id'], routing_type['name']]) - env.fout(table) diff --git a/SoftLayer/CLI/loadbal/service_add.py b/SoftLayer/CLI/loadbal/service_add.py deleted file mode 100644 index 38d590392..000000000 --- a/SoftLayer/CLI/loadbal/service_add.py +++ /dev/null @@ -1,53 +0,0 @@ -"""Adds a new load balancer service.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@click.option('--enabled / --disabled', - required=True, - help="Create the service as enabled or disabled") -@click.option('--port', - required=True, - help="The port number for the service", - type=click.INT) -@click.option('--weight', - required=True, - type=click.INT, - help="The weight of the service") -@click.option('--healthcheck-type', - required=True, - help="The health check type") -@click.option('--ip-address', - required=True, - help="The IP address of the service") -@environment.pass_env -def cli(env, identifier, enabled, port, weight, healthcheck_type, ip_address): - """Adds a new load balancer service.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - - loadbal_id, group_id = loadbal.parse_id(identifier) - - # check if the IP is valid - ip_address_id = None - if ip_address: - ip_service = env.client['Network_Subnet_IpAddress'] - ip_record = ip_service.getByIpAddress(ip_address) - if len(ip_record) > 0: - ip_address_id = ip_record['id'] - - mgr.add_service(loadbal_id, - group_id, - ip_address_id=ip_address_id, - enabled=enabled, - port=port, - weight=weight, - hc_type=healthcheck_type) - env.fout('Load balancer service is being added!') diff --git a/SoftLayer/CLI/loadbal/service_delete.py b/SoftLayer/CLI/loadbal/service_delete.py deleted file mode 100644 index 130b2146e..000000000 --- a/SoftLayer/CLI/loadbal/service_delete.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Deletes an existing load balancer service.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions -from SoftLayer.CLI import formatting -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@environment.pass_env -def cli(env, identifier): - """Deletes an existing load balancer service.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - _, service_id = loadbal.parse_id(identifier) - - if not (env.skip_confirmations or - formatting.confirm("This action will cancel a service from your " - "load balancer. Continue?")): - raise exceptions.CLIAbort('Aborted.') - - mgr.delete_service(service_id) - env.fout('Load balancer service %s is being cancelled!' % service_id) diff --git a/SoftLayer/CLI/loadbal/service_edit.py b/SoftLayer/CLI/loadbal/service_edit.py deleted file mode 100644 index e8734cd50..000000000 --- a/SoftLayer/CLI/loadbal/service_edit.py +++ /dev/null @@ -1,52 +0,0 @@ -"""Edit the properties of a service group.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@click.option('--enabled / --disabled', - default=None, - help="Enable or disable the service") -@click.option('--port', - help="Change the port number for the service", type=click.INT) -@click.option('--weight', - type=click.INT, - help="Change the weight of the service") -@click.option('--healthcheck-type', help="Change the health check type") -@click.option('--ip-address', help="Change the IP address of the service") -@environment.pass_env -def cli(env, identifier, enabled, port, weight, healthcheck_type, ip_address): - """Edit the properties of a service group.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - - loadbal_id, service_id = loadbal.parse_id(identifier) - - # check if any input is provided - if ((not any([ip_address, weight, port, healthcheck_type])) and - enabled is None): - raise exceptions.CLIAbort( - 'At least one property is required to be changed!') - - # check if the IP is valid - ip_address_id = None - if ip_address: - ip_service = env.client['Network_Subnet_IpAddress'] - ip_record = ip_service.getByIpAddress(ip_address) - ip_address_id = ip_record['id'] - - mgr.edit_service(loadbal_id, - service_id, - ip_address_id=ip_address_id, - enabled=enabled, - port=port, - weight=weight, - hc_type=healthcheck_type) - env.fout('Load balancer service %s is being modified!' % identifier) diff --git a/SoftLayer/CLI/loadbal/service_toggle.py b/SoftLayer/CLI/loadbal/service_toggle.py deleted file mode 100644 index 799b4333c..000000000 --- a/SoftLayer/CLI/loadbal/service_toggle.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Toggle the status of an existing load balancer service.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import exceptions -from SoftLayer.CLI import formatting -from SoftLayer.CLI import loadbal - - -@click.command() -@click.argument('identifier') -@environment.pass_env -def cli(env, identifier): - """Toggle the status of an existing load balancer service.""" - - mgr = SoftLayer.LoadBalancerManager(env.client) - _, service_id = loadbal.parse_id(identifier) - - if not (env.skip_confirmations or - formatting.confirm("This action will toggle the status on the " - "service. Continue?")): - raise exceptions.CLIAbort('Aborted.') - - mgr.toggle_service_status(service_id) - env.fout('Load balancer service %s status updated!' % identifier) diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index 5524b6948..c87ad4296 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -167,22 +167,13 @@ ('ipsec:update', 'SoftLayer.CLI.vpn.ipsec.update:cli'), ('loadbal', 'SoftLayer.CLI.loadbal'), - ('loadbal:cancel', 'SoftLayer.CLI.loadbal.cancel:cli'), - ('loadbal:create', 'SoftLayer.CLI.loadbal.create:cli'), - ('loadbal:create-options', 'SoftLayer.CLI.loadbal.create_options:cli'), ('loadbal:detail', 'SoftLayer.CLI.loadbal.detail:cli'), - ('loadbal:group-add', 'SoftLayer.CLI.loadbal.group_add:cli'), - ('loadbal:group-delete', 'SoftLayer.CLI.loadbal.group_delete:cli'), - ('loadbal:group-edit', 'SoftLayer.CLI.loadbal.group_edit:cli'), - ('loadbal:group-reset', 'SoftLayer.CLI.loadbal.group_reset:cli'), - ('loadbal:health-checks', 'SoftLayer.CLI.loadbal.health_checks:cli'), ('loadbal:list', 'SoftLayer.CLI.loadbal.list:cli'), - ('loadbal:routing-methods', 'SoftLayer.CLI.loadbal.routing_methods:cli'), - ('loadbal:routing-types', 'SoftLayer.CLI.loadbal.routing_types:cli'), - ('loadbal:service-add', 'SoftLayer.CLI.loadbal.service_add:cli'), - ('loadbal:service-delete', 'SoftLayer.CLI.loadbal.service_delete:cli'), - ('loadbal:service-edit', 'SoftLayer.CLI.loadbal.service_edit:cli'), - ('loadbal:service-toggle', 'SoftLayer.CLI.loadbal.service_toggle:cli'), + ('loadbal:health', 'SoftLayer.CLI.loadbal.health:cli'), + + ('loadbal:ns-detail', 'SoftLayer.CLI.loadbal.ns_detail:cli'), + ('loadbal:ns-list', 'SoftLayer.CLI.loadbal.ns_list:cli'), + ('metadata', 'SoftLayer.CLI.metadata:cli'), diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 854c8c620..217e3b495 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -11,7 +11,7 @@ class LoadBalancerManager(utils.IdentifierMixin, object): """Manages SoftLayer load balancers. - See product information here: http://www.softlayer.com/load-balancing + See product information here: https://www.ibm.com/cloud/load-balancer :param SoftLayer.API.BaseClient client: the client instance @@ -21,8 +21,56 @@ def __init__(self, client): self.client = client self.account = self.client['Account'] self.prod_pkg = self.client['Product_Package'] - self.lb_svc = self.client['Network_Application_Delivery_Controller_' - 'LoadBalancer_VirtualIpAddress'] + # Citrix Netscalers + self.adc = self.client['Network_Application_Delivery_Controller'] + # IBM CLoud LB + self.lbaas = self.client['Network_LBaaS_LoadBalancer'] + + def get_adcs(self, mask=None): + """Returns a list of all netscalers. + + :returns: SoftLayer_Network_Application_Delivery_Controller[]. + """ + if mask is None: + mask = 'mask[managementIpAddress,outboundPublicBandwidthUsage,primaryIpAddress,datacenter]' + return self.account.getApplicationDeliveryControllers(mask=mask) + + def get_adc(self, identifier, mask=None): + """Returns a netscaler object. + + :returns: SoftLayer_Network_Application_Delivery_Controller. + """ + if mask is None: + mask = "mask[networkVlans, password, managementIpAddress, primaryIpAddress, subnets, tagReferences, " \ + "licenseExpirationDate, datacenter]" + return self.adc.getObject(id=identifier, mask=mask) + + def get_lbaas(self, mask=None): + """Returns a list of IBM Cloud Loadbalancers + + :returns: SoftLayer_Network_LBaaS_LoadBalancer[] + """ + if mask is None: + mask = "mask[datacenter,listenerCount,memberCount]" + lb = self.lbaas.getAllObjects(mask=mask) + + return lb + + def get_lb(self, identifier, mask=None): + """Returns a IBM Cloud LoadBalancer + + :returns: SoftLayer_Network_LBaaS_LoadBalancer + """ + if mask is None: + mask = "mask[healthMonitors, l7Pools, listeners[defaultPool[healthMonitor, members, sessionAffinity],l7Policies], members, sslCiphers]" + + lb = self.lbaas.getObject(id=identifier, mask=mask) + health = self.lbaas.getLoadBalancerMemberHealth(lb.get('uuid')) + + lb['health'] = health + return lb + +# Old things below this line def get_lb_pkgs(self): """Retrieves the local load balancer packages. @@ -114,14 +162,7 @@ def add_local_lb(self, price_item_id, datacenter): } return self.client['Product_Order'].placeOrder(product_order) - def get_local_lbs(self): - """Returns a list of all local load balancers on the account. - - :returns: A list of all local load balancers on the current account. - """ - mask = 'loadBalancerHardware[datacenter],ipAddress' - return self.account.getAdcLoadBalancers(mask=mask) def get_local_lb(self, loadbal_id, **kwargs): """Returns a specified local load balancer given the id. diff --git a/SoftLayer/utils.py b/SoftLayer/utils.py index b70997842..21138e6ae 100644 --- a/SoftLayer/utils.py +++ b/SoftLayer/utils.py @@ -306,6 +306,8 @@ def clean_time(sltime, in_format='%Y-%m-%dT%H:%M:%S%z', out_format='%Y-%m-%d %H: :param string in_format: Datetime format for strptime :param string out_format: Datetime format for strftime """ + if sltime is None: + return None try: clean = datetime.datetime.strptime(sltime, in_format) return clean.strftime(out_format) From c68eafa00e2241fdffc3c8499782e41a9739c9d4 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Thu, 11 Jul 2019 16:49:58 -0500 Subject: [PATCH 02/23] #1047 manage health checks --- SoftLayer/CLI/loadbal/edit_members.py | 0 SoftLayer/CLI/loadbal/health.py | 56 +++++++++++++++++++++++++-- SoftLayer/CLI/routes.py | 1 + SoftLayer/managers/load_balancer.py | 36 ++++++++++++++++- 4 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 SoftLayer/CLI/loadbal/edit_members.py diff --git a/SoftLayer/CLI/loadbal/edit_members.py b/SoftLayer/CLI/loadbal/edit_members.py new file mode 100644 index 000000000..e69de29bb diff --git a/SoftLayer/CLI/loadbal/health.py b/SoftLayer/CLI/loadbal/health.py index d101b9b30..d487ee535 100644 --- a/SoftLayer/CLI/loadbal/health.py +++ b/SoftLayer/CLI/loadbal/health.py @@ -3,18 +3,66 @@ import SoftLayer from SoftLayer.CLI import environment +from SoftLayer.CLI import exceptions from SoftLayer.CLI import formatting +from SoftLayer.CLI import helpers from SoftLayer import utils from pprint import pprint as pp @click.command() @click.argument('identifier') +@click.option('--uuid', required=True, help="Health check UUID to modify.") +@click.option('--interval', '-i', type=click.IntRange(2, 60), help="Seconds between checks. [2-60]") +@click.option('--retry', '-r', type=click.IntRange(1, 10), help="Number of times before marking as DOWN. [1-10]") +@click.option('--timeout', '-t', type=click.IntRange(1, 59), help="Seconds to wait for a connection. [1-59]") +@click.option('--url', '-u', help="Url path for HTTP/HTTPS checks.") @environment.pass_env -def cli(env, identifier): +def cli(env, identifier, uuid, interval, retry, timeout, url): """Manage LBaaS health checks.""" + + if not any([interval, retry, timeout, url]): + raise exceptions.ArgumentError("Specify either interval, retry, timeout, url") + + # map parameters to expected API names + template = {'healthMonitorUuid': uuid, 'interval': interval, 'maxRetries': retry, 'timeout': timeout, 'urlPath': url} + # Removes those empty values + clean_template = {k: v for k, v in template.items() if v is not None} + mgr = SoftLayer.LoadBalancerManager(env.client) + # Need to get the LBaaS uuid if it wasn't supplied + lb_uuid, lb_id = mgr.get_lbaas_uuid_id(identifier) + print("UUID: {}, ID: {}".format(lb_uuid, lb_id)) + + # Get the current health checks, and find the one we are updating. + mask = "mask[healthMonitors, listeners[uuid,defaultPool[healthMonitor]]]" + lbaas = mgr.get_lb(lb_id, mask=mask) + + check = {} + # Set the default values, because these all need to be set if we are not updating them. + for listener in lbaas.get('listeners', []): + if utils.lookup(listener, 'defaultPool', 'healthMonitor', 'uuid') == uuid: + check['backendProtocol'] = utils.lookup(listener, 'defaultPool', 'protocol') + check['backendPort'] = utils.lookup(listener, 'defaultPool', 'protocolPort') + check['healthMonitorUuid'] = uuid + check['interval'] = utils.lookup(listener, 'defaultPool', 'healthMonitor', 'interval') + check['maxRetries'] = utils.lookup(listener, 'defaultPool', 'healthMonitor', 'maxRetries') + check['timeout'] = utils.lookup(listener, 'defaultPool', 'healthMonitor', 'timeout') + check['urlPath'] = utils.lookup(listener, 'defaultPool', 'healthMonitor', 'urlPath') + + + if url and check['backendProtocol'] == 'TCP': + raise exceptions.ArgumentError('--url cannot be used with TCP checks') + + # Update existing check with supplied values + for key in clean_template.keys(): + check[key] = clean_template[key] + + result = mgr.updateLoadBalancerHealthMonitors(lb_uuid, [check]) + + if result: + click.secho('Health Check {} updated successfully'.format(uuid), fg='green') + else: + click.secho('ERROR: Failed to update {}'.format(uuid), fg='red') + - lb = mgr.get_lb(identifier) - table = lbaas_table(lb) - env.fout(table) diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index c87ad4296..b73a753d3 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -170,6 +170,7 @@ ('loadbal:detail', 'SoftLayer.CLI.loadbal.detail:cli'), ('loadbal:list', 'SoftLayer.CLI.loadbal.list:cli'), ('loadbal:health', 'SoftLayer.CLI.loadbal.health:cli'), + ('loadbal:edit-members', 'SoftLayer.CLI.loadbal.edit_members:cli'), ('loadbal:ns-detail', 'SoftLayer.CLI.loadbal.ns_detail:cli'), ('loadbal:ns-list', 'SoftLayer.CLI.loadbal.ns_list:cli'), diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 217e3b495..2ff50f578 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -26,6 +26,8 @@ def __init__(self, client): # IBM CLoud LB self.lbaas = self.client['Network_LBaaS_LoadBalancer'] + + def get_adcs(self, mask=None): """Returns a list of all netscalers. @@ -62,7 +64,8 @@ def get_lb(self, identifier, mask=None): :returns: SoftLayer_Network_LBaaS_LoadBalancer """ if mask is None: - mask = "mask[healthMonitors, l7Pools, listeners[defaultPool[healthMonitor, members, sessionAffinity],l7Policies], members, sslCiphers]" + mask = "mask[healthMonitors, l7Pools, members, sslCiphers, " \ + "listeners[defaultPool[healthMonitor, members, sessionAffinity],l7Policies]]" lb = self.lbaas.getObject(id=identifier, mask=mask) health = self.lbaas.getLoadBalancerMemberHealth(lb.get('uuid')) @@ -70,6 +73,37 @@ def get_lb(self, identifier, mask=None): lb['health'] = health return lb + def get_lb_monitors(self, identifier, mask=None): + health = self.lbaas.getHealthMonitors(id=identifier) + return health + + def updateLoadBalancerHealthMonitors(self, uuid, checks): + """calls SoftLayer_Network_LBaaS_HealthMonitor::updateLoadBalancerHealthMonitors() + + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_HealthMonitor/updateLoadBalancerHealthMonitors/ + https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_LoadBalancerHealthMonitorConfiguration/ + :param uuid: loadBalancerUuid + :param checks list: SoftLayer_Network_LBaaS_LoadBalancerHealthMonitorConfiguration[] + """ + + # return self.lbaas.updateLoadBalancerHealthMonitors(uuid, checks) + return self.client.call('SoftLayer_Network_LBaaS_HealthMonitor', 'updateLoadBalancerHealthMonitors', + uuid, checks) + + def get_lbaas_uuid_id(self, identifier): + """Gets a LBaaS uuid, id. Since sometimes you need one or the other. + + :param identifier: either the LB Id, or UUID, this function will return both. + :return (uuid, id): + """ + if len(identifier) == 36: + lb = self.lbaas.getLoadBalancer(id=identifier, mask="mask[id,uuid]") + return identifier + else: + print("Finding out %s" % identifier) + lb = self.lbaas.getObject(id=identifier, mask="mask[id,uuid]") + return lb['uuid'], lb['id'] + # Old things below this line def get_lb_pkgs(self): From 1b907bff72d08a3b7f4af429a26a2871f298fdfb Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Mon, 15 Jul 2019 15:36:56 -0500 Subject: [PATCH 03/23] lbaas member-add and member-del commands --- SoftLayer/CLI/loadbal/detail.py | 9 ++-- SoftLayer/CLI/loadbal/edit_members.py | 0 SoftLayer/CLI/loadbal/list.py | 1 + SoftLayer/CLI/loadbal/members.py | 62 +++++++++++++++++++++++++++ SoftLayer/CLI/routes.py | 3 +- SoftLayer/managers/load_balancer.py | 28 ++++++++++-- 6 files changed, 96 insertions(+), 7 deletions(-) delete mode 100644 SoftLayer/CLI/loadbal/edit_members.py create mode 100644 SoftLayer/CLI/loadbal/members.py diff --git a/SoftLayer/CLI/loadbal/detail.py b/SoftLayer/CLI/loadbal/detail.py index 6f29e7655..14726eaa0 100644 --- a/SoftLayer/CLI/loadbal/detail.py +++ b/SoftLayer/CLI/loadbal/detail.py @@ -13,9 +13,12 @@ def cli(env, identifier): """Get Load Balancer as a Service details.""" mgr = SoftLayer.LoadBalancerManager(env.client) - - lb = mgr.get_lb(identifier) - pp(lb) + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + lb = mgr.get_lb(lbid) + # pp(lb) + if lb.get('previousErrorText'): + print("THERE WAS AN ERROR") + print(lb.get('previousErrorText')) table = lbaas_table(lb) env.fout(table) diff --git a/SoftLayer/CLI/loadbal/edit_members.py b/SoftLayer/CLI/loadbal/edit_members.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/SoftLayer/CLI/loadbal/list.py b/SoftLayer/CLI/loadbal/list.py index e8394170c..228a98ec6 100644 --- a/SoftLayer/CLI/loadbal/list.py +++ b/SoftLayer/CLI/loadbal/list.py @@ -37,6 +37,7 @@ def generate_lbaas_table(lbaas): table.align['Description'] = 'l' table.align['Location'] = 'l' for lb in sorted(lbaas,key=location_sort): + print("PUBLIC: {}".format(lb.get('isPublic'))) table.add_row([ lb.get('id'), utils.lookup(lb, 'datacenter', 'longName'), diff --git a/SoftLayer/CLI/loadbal/members.py b/SoftLayer/CLI/loadbal/members.py new file mode 100644 index 000000000..0f0ffe228 --- /dev/null +++ b/SoftLayer/CLI/loadbal/members.py @@ -0,0 +1,62 @@ +"""Manage LBaaS members.""" +import click + +import SoftLayer +from SoftLayer.CLI import environment, formatting, helpers +from SoftLayer.exceptions import SoftLayerAPIError +from SoftLayer import utils +from pprint import pprint as pp + +@click.command() +@click.argument('identifier') +@click.option('--member', '-m', required=True, help="Member UUID") +@environment.pass_env +def remove(env, identifier, member): + """Remove a LBaaS member. + + Member UUID can be found from `slcli lb detail`. + """ + + mgr = SoftLayer.LoadBalancerManager(env.client) + + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + # Get a member ID to remove + + try: + result = mgr.delete_lb_member(uuid, member) + click.secho("Member {} removed".format(member), fg='green') + except SoftLayerAPIError as e: + click.secho("ERROR: {}".format(e.faultString), fg='red') + + +@click.command() +@click.argument('identifier') +@click.option('--private/--public', default=True, required=True, help="Private or public IP of the new member.") +@click.option('--member', '-m', required=True, help="Member IP address.") +@click.option('--weight', '-w', default=50, type=int, help="Weight of this member.") +@environment.pass_env +def add(env, identifier, private, member, weight): + """Add a new LBaaS members.""" + + mgr = SoftLayer.LoadBalancerManager(env.client) + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + # Get a server ID to add + to_add = {"weight": weight} + if private: + to_add['privateIpAddress'] = member + else: + to_add['publicIpAddress'] = member + + try: + result = mgr.add_lb_member(uuid, to_add) + click.secho("Member {} added".format(member), fg='green') + except SoftLayerAPIError as e: + if 'publicIpAddress must be a string' in e.faultString: + click.secho("This LB requires a Public IP address for its members and none was supplied", fg='red') + elif 'privateIpAddress must be a string' in e.faultString: + click.secho("This LB requires a Private IP address for its members and none was supplied", fg='red') + click.secho("ERROR: {}".format(e.faultString), fg='red') + + + + diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index b73a753d3..b95adcd12 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -170,7 +170,8 @@ ('loadbal:detail', 'SoftLayer.CLI.loadbal.detail:cli'), ('loadbal:list', 'SoftLayer.CLI.loadbal.list:cli'), ('loadbal:health', 'SoftLayer.CLI.loadbal.health:cli'), - ('loadbal:edit-members', 'SoftLayer.CLI.loadbal.edit_members:cli'), + ('loadbal:member-add', 'SoftLayer.CLI.loadbal.members:add'), + ('loadbal:member-del', 'SoftLayer.CLI.loadbal.members:remove'), ('loadbal:ns-detail', 'SoftLayer.CLI.loadbal.ns_detail:cli'), ('loadbal:ns-list', 'SoftLayer.CLI.loadbal.ns_list:cli'), diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 2ff50f578..a042e79f7 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -97,13 +97,35 @@ def get_lbaas_uuid_id(self, identifier): :return (uuid, id): """ if len(identifier) == 36: - lb = self.lbaas.getLoadBalancer(id=identifier, mask="mask[id,uuid]") - return identifier + lb = self.lbaas.getLoadBalancer(identifier, mask="mask[id,uuid]") else: - print("Finding out %s" % identifier) lb = self.lbaas.getObject(id=identifier, mask="mask[id,uuid]") return lb['uuid'], lb['id'] + def delete_lb_member(self, identifier, member_id): + """Removes a member from a LBaaS instance + + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_Member/deleteLoadBalancerMembers/ + :param identifier: UUID of the LBaaS instance + :param member_id: Member UUID to remove. + """ + result = self.client.call('SoftLayer_Network_LBaaS_Member', 'deleteLoadBalancerMembers', + identifier, [member_id]) + return result + + def add_lb_member(self, identifier, member_id): + """Removes a member from a LBaaS instance + + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_Member/deleteLoadBalancerMembers/ + :param identifier: UUID of the LBaaS instance + :param member_id: Member UUID to remove. + """ + + result = self.client.call('SoftLayer_Network_LBaaS_Member', 'addLoadBalancerMembers', + identifier, [member_id]) + + return result + # Old things below this line def get_lb_pkgs(self): From feab68df0bb3d6a69848d0cd1c648412b366adb0 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 17 Jul 2019 15:50:02 -0500 Subject: [PATCH 04/23] LB pool management commands --- SoftLayer/CLI/loadbal/pools.py | 119 ++++++++++++++++++++++++++++ SoftLayer/CLI/routes.py | 3 + SoftLayer/managers/load_balancer.py | 26 ++++++ 3 files changed, 148 insertions(+) create mode 100644 SoftLayer/CLI/loadbal/pools.py diff --git a/SoftLayer/CLI/loadbal/pools.py b/SoftLayer/CLI/loadbal/pools.py new file mode 100644 index 000000000..8accc5e3a --- /dev/null +++ b/SoftLayer/CLI/loadbal/pools.py @@ -0,0 +1,119 @@ +"""Manage LBaaS Pools/Listeners.""" +import click + +import SoftLayer +from SoftLayer.CLI import environment, formatting, helpers +from SoftLayer.exceptions import SoftLayerAPIError +from SoftLayer import utils +from pprint import pprint as pp + + +def sticky_option(ctx, param, value): + if value: + return 'SOURCE_IP' + return None + +@click.command() +@click.argument('identifier') +@click.option('--frontProtocol', '-P', default='HTTP', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), show_default=True, + help="Protocol type to use for incoming connections") +@click.option('--backProtocol', '-p', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), + help="Protocol type to use when connecting to backend servers. Defaults to whatever --frontProtocol is.") +@click.option('--frontPort', '-f', required=True, type=int, help="Internet side port") +@click.option('--backPort', '-b', required=True, type=int, help="Private side port") +@click.option('--method', '-m', default='ROUNDROBIN', show_default=True, help="Balancing Method", + type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) +@click.option('--connections', '-c', type=int, help="Maximum number of connections to allow.") +@click.option('--sticky', '-s', is_flag=True, callback=sticky_option, help="Make sessions sticky based on source_ip.") +@environment.pass_env +def add(env, identifier, **args): + """Adds a listener to the identifier LB""" + + mgr = SoftLayer.LoadBalancerManager(env.client) + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + + new_listener = { + 'backendPort': args.get('backport'), + 'backendProtocol': args.get('backprotocol') if args.get('backprotocol') else args.get('frontprotocol'), + 'frontendPort': args.get('frontport'), + 'frontendProtocol': args.get('frontprotocol'), + 'loadBalancingMethod': args.get('method'), + 'maxConn': args.get('connections', None), + 'sessionType': args.get('sticky'), + 'tlsCertificateId': None + } + + try: + result = mgr.add_lb_listener(uuid, new_listener) + click.secho("Success", fg='green') + except SoftLayerAPIError as e: + click.secho("ERROR: {}".format(e.faultString), fg='red') + + +@click.command() +@click.argument('identifier') +@click.argument('listener') +@click.option('--frontProtocol', '-P', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), + help="Protocol type to use for incoming connections") +@click.option('--backProtocol', '-p', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), + help="Protocol type to use when connecting to backend servers. Defaults to whatever --frontProtocol is.") +@click.option('--frontPort', '-f', type=int, help="Internet side port") +@click.option('--backPort', '-b', type=int, help="Private side port") +@click.option('--method', '-m', help="Balancing Method", + type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) +@click.option('--connections', '-c', type=int, help="Maximum number of connections to allow.") +@click.option('--sticky', '-s', is_flag=True, callback=sticky_option, help="Make sessions sticky based on source_ip.") +@environment.pass_env +def edit(env, identifier, listener, **args): + """Updates a listener's configuration. + + LISTENER should be a UUID, and can be found from `slcli lb detail ` + """ + + mgr = SoftLayer.LoadBalancerManager(env.client) + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + + + new_listener = { + 'listenerUuid': listener + } + + arg_to_option = { + 'frontprotocol': 'frontendProtocol', + 'backprotocol': 'backendProtocol', + 'frontport': 'frontendPort', + 'backport': 'backendPort', + 'method': 'loadBalancingMethod', + 'connections': 'maxConn', + 'sticky': 'sessionType', + 'sslcert': 'tlsCertificateId' + } + + for arg in args.keys(): + if args[arg]: + new_listener[arg_to_option[arg]] = args[arg] + + try: + result = mgr.add_lb_listener(uuid, new_listener) + click.secho("Success", fg='green') + except SoftLayerAPIError as e: + click.secho("ERROR: {}".format(e.faultString), fg='red') + + +@click.command() +@click.argument('identifier') +@click.argument('listener') +@environment.pass_env +def delete(env, identifier, listener): + """Removes the listener from identified LBaaS instance + + LISTENER should be a UUID, and can be found from `slcli lb detail ` + """ + + mgr = SoftLayer.LoadBalancerManager(env.client) + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + try: + result = mgr.remove_lb_listener(uuid, listener) + click.secho("Success", fg='green') + except SoftLayerAPIError as e: + click.secho("ERROR: {}".format(e.faultString), fg='red') \ No newline at end of file diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index b95adcd12..fa8c8e77d 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -172,6 +172,9 @@ ('loadbal:health', 'SoftLayer.CLI.loadbal.health:cli'), ('loadbal:member-add', 'SoftLayer.CLI.loadbal.members:add'), ('loadbal:member-del', 'SoftLayer.CLI.loadbal.members:remove'), + ('loadbal:pool-add', 'SoftLayer.CLI.loadbal.pools:add'), + ('loadbal:pool-edit', 'SoftLayer.CLI.loadbal.pools:edit'), + ('loadbal:pool-del', 'SoftLayer.CLI.loadbal.pools:delete'), ('loadbal:ns-detail', 'SoftLayer.CLI.loadbal.ns_detail:cli'), ('loadbal:ns-list', 'SoftLayer.CLI.loadbal.ns_list:cli'), diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index a042e79f7..3777f0c96 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -126,6 +126,32 @@ def add_lb_member(self, identifier, member_id): return result + def add_lb_listener(self, identifier, listener): + """Adds or update a listener to a LBaaS instance + + When using this to update a listener, just include the 'listenerUuid' in the listener object + See the following for listener configuration options + https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_LoadBalancerProtocolConfiguration/ + + :param identifier: UUID of the LBaaS instance + :param listener: Object with all listener configurations + """ + + result = self.client.call('SoftLayer_Network_LBaaS_Listener', 'updateLoadBalancerProtocols', + identifier, [listener]) + return result + + def remove_lb_listener(self, identifier, listener): + """Removes a listener to a LBaaS instance + + :param identifier: UUID of the LBaaS instance + :param listener: UUID of the Listner to be removed. + """ + + result = self.client.call('SoftLayer_Network_LBaaS_Listener', 'deleteLoadBalancerProtocols', + identifier, [listener]) + return result + # Old things below this line def get_lb_pkgs(self): From 6132b58cfdfba0f37909a7f522cf0cd965e436bf Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Thu, 18 Jul 2019 17:13:37 -0500 Subject: [PATCH 05/23] work around l7 pools --- SoftLayer/CLI/loadbal/pools.py | 85 ++++++++++++++++++++++++++++- SoftLayer/CLI/routes.py | 1 + SoftLayer/managers/load_balancer.py | 54 ++++++++++++++++++ 3 files changed, 137 insertions(+), 3 deletions(-) diff --git a/SoftLayer/CLI/loadbal/pools.py b/SoftLayer/CLI/loadbal/pools.py index 8accc5e3a..7ada89118 100644 --- a/SoftLayer/CLI/loadbal/pools.py +++ b/SoftLayer/CLI/loadbal/pools.py @@ -2,7 +2,7 @@ import click import SoftLayer -from SoftLayer.CLI import environment, formatting, helpers +from SoftLayer.CLI import environment, formatting, helpers, exceptions from SoftLayer.exceptions import SoftLayerAPIError from SoftLayer import utils from pprint import pprint as pp @@ -25,6 +25,7 @@ def sticky_option(ctx, param, value): type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) @click.option('--connections', '-c', type=int, help="Maximum number of connections to allow.") @click.option('--sticky', '-s', is_flag=True, callback=sticky_option, help="Make sessions sticky based on source_ip.") +@click.option('--sslCert', '-x', help="SSL certificate ID. See `slcli ssl list`") @environment.pass_env def add(env, identifier, **args): """Adds a listener to the identifier LB""" @@ -40,7 +41,7 @@ def add(env, identifier, **args): 'loadBalancingMethod': args.get('method'), 'maxConn': args.get('connections', None), 'sessionType': args.get('sticky'), - 'tlsCertificateId': None + 'tlsCertificateId': args.get('sslcert') } try: @@ -63,6 +64,7 @@ def add(env, identifier, **args): type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) @click.option('--connections', '-c', type=int, help="Maximum number of connections to allow.") @click.option('--sticky', '-s', is_flag=True, callback=sticky_option, help="Make sessions sticky based on source_ip.") +@click.option('--sslCert', '-x', help="SSL certificate ID. See `slcli ssl list`") @environment.pass_env def edit(env, identifier, listener, **args): """Updates a listener's configuration. @@ -116,4 +118,81 @@ def delete(env, identifier, listener): result = mgr.remove_lb_listener(uuid, listener) click.secho("Success", fg='green') except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') \ No newline at end of file + click.secho("ERROR: {}".format(e.faultString), fg='red') + +def parse_server(ctx, param, values): + """Splits out the IP, Port, Weight from the --server argument for l7pools""" + servers = [] + for server in values: + splitout = server.split(':') + if len(splitout) != 3: + raise exceptions.ArgumentError("--server needs a port and a weight. {} improperly formatted".format(server)) + server = { + 'address': splitout[0], + 'port': splitout[1], + 'weight': splitout[2] + } + servers.append(server) + + return servers + +@click.command() +@click.argument('identifier') +# https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7Pool/ +@click.option('--name', '-n', required=True, help="Name for this L7 pool.") +@click.option('--method', '-m', help="Balancing Method.", default='ROUNDROBIN', show_default=True, + type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) +@click.option('--protocol', '-P', type=click.Choice(['HTTP', 'HTTPS']), default='HTTP', + show_default=True, help="Protocol type to use for incoming connections") +# https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7Member/ +@helpers.multi_option('--server', '-S', callback=parse_server, required=True, + help="Backend servers that are part of this pool. Format is colon deliminated. " \ + "BACKEND_IP:PORT:WEIGHT. eg. 10.0.0.1:80:50") +# https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7HealthMonitor/ +@click.option('--healthPath', default='/', show_default=True, help="Health check path.") +@click.option('--healthInterval', default=5, type=int, show_default=True, help="Health check interval between checks.") +@click.option('--healthRetry', default=2, type=int, show_default=True, + help="Health check number of times before marking as DOWN.") +@click.option('--healthTimeout', default=2, type=int, show_default=True, help="Health check timeout.") +# https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7SessionAffinity/ +@click.option('--sticky', '-s', is_flag=True, callback=sticky_option, help="Make sessions sticky based on source_ip.") +@environment.pass_env +def l7pool_add(env, identifier, **args): + """Adds a new l7 pool + + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_L7Pool/createL7Pool/ + + -S is in : deliminated format to make grouping IP:port:weight a bit easier. + """ + + mgr = SoftLayer.LoadBalancerManager(env.client) + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + + pool_main = { + 'name': args.get('name'), + 'loadBalancingAlgorithm': args.get('method'), + 'protocol': args.get('protocol') + } + + pool_members = [member for member in args.get('server')] + + pool_health = { + 'interval': args.get('healthinterval'), + 'timeout': args.get('healthtimeout'), + 'maxRetries': args.get('healthretry'), + 'urlPath': args.get('healthpath') + } + + pool_sticky = { + 'type': args.get('sticky') + } + + try: + result = mgr.add_lb_l7_pool(uuid, pool_main, pool_members, pool_health, None) + pp(result) + click.secho("Success", fg='green') + except SoftLayerAPIError as e: + click.secho("ERROR: {}".format(e.faultString), fg='red') + + + diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index fa8c8e77d..d637fa866 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -175,6 +175,7 @@ ('loadbal:pool-add', 'SoftLayer.CLI.loadbal.pools:add'), ('loadbal:pool-edit', 'SoftLayer.CLI.loadbal.pools:edit'), ('loadbal:pool-del', 'SoftLayer.CLI.loadbal.pools:delete'), + ('loadbal:l7pool-add', 'SoftLayer.CLI.loadbal.pools:l7pool_add'), ('loadbal:ns-detail', 'SoftLayer.CLI.loadbal.ns_detail:cli'), ('loadbal:ns-list', 'SoftLayer.CLI.loadbal.ns_list:cli'), diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 3777f0c96..6592d0433 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -141,6 +141,60 @@ def add_lb_listener(self, identifier, listener): identifier, [listener]) return result + def add_lb_l7_pool(self, identifier, pool, members, health, session): + """Creates a new l7 pool for a LBaaS instance + + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_L7Pool/createL7Pool/ + https://cloud.ibm.com/docs/infrastructure/loadbalancer-service?topic=loadbalancer-service-api-reference + + :param identifier: UUID of the LBaaS instance + :param pool SoftLayer_Network_LBaaS_L7Pool: Description of the pool + :param members SoftLayer_Network_LBaaS_L7Member[]: Array of servers with their address, port, weight + :param monitor SoftLayer_Network_LBaaS_L7HealthMonitor: A health monitor + :param session SoftLayer_Network_LBaaS_L7SessionAffinity: Weather to use affinity + """ + + l7Members = [ + { + 'address': '10.131.11.60', + 'port': 82, + 'weight': 10 + }, + { + 'address': '10.131.11.46', + 'port': 83, + 'weight': 11 + } + ] + + l7Pool = { + 'name': 'image112_pool', + 'protocol': 'HTTP', # only supports HTTP + 'loadBalancingAlgorithm': 'ROUNDROBIN' + } + + l7HealthMonitor = { + 'interval': 10, + 'timeout': 5, + 'maxRetries': 3, + 'urlPath': '/' + } + + # Layer 7 session affinity to be added. Only supports SOURCE_IP as of now + l7SessionAffinity = { + 'type': 'SOURCE_IP' + } + + # result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', + # identifier, pool, members, health, session) + result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', + identifier, l7Pool, l7Members, l7HealthMonitor, l7SessionAffinity) + + + # string, member, monitor, affinity + + return result + def remove_lb_listener(self, identifier, listener): """Removes a listener to a LBaaS instance From f378a8ea9a5a257e1a09275dbf99ef666700f84d Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Mon, 29 Jul 2019 18:10:54 -0500 Subject: [PATCH 06/23] loadbalancer order options command --- SoftLayer/CLI/loadbal/detail.py | 3 +- SoftLayer/CLI/loadbal/order.py | 107 ++++++++++++++++++++++++++++ SoftLayer/CLI/loadbal/pools.py | 21 ++++-- SoftLayer/CLI/routes.py | 5 ++ SoftLayer/managers/load_balancer.py | 91 ++++++++++++++--------- 5 files changed, 186 insertions(+), 41 deletions(-) create mode 100644 SoftLayer/CLI/loadbal/order.py diff --git a/SoftLayer/CLI/loadbal/detail.py b/SoftLayer/CLI/loadbal/detail.py index 14726eaa0..545c19cde 100644 --- a/SoftLayer/CLI/loadbal/detail.py +++ b/SoftLayer/CLI/loadbal/detail.py @@ -52,9 +52,10 @@ def lbaas_table(lb): table.add_row(['Checks', hp_table]) # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7Pool/ - l7_table = formatting.Table(['UUID', 'Balancer', 'Name', 'Protocol', 'Modify', 'Active' ]) + l7_table = formatting.Table(['Id', 'UUID', 'Balancer', 'Name', 'Protocol', 'Modify', 'Active' ]) for l7 in lb.get('l7Pools', []): l7_table.add_row([ + l7.get('id'), l7.get('uuid'), l7.get('loadBalancingAlgorithm'), l7.get('name'), diff --git a/SoftLayer/CLI/loadbal/order.py b/SoftLayer/CLI/loadbal/order.py new file mode 100644 index 000000000..71440063c --- /dev/null +++ b/SoftLayer/CLI/loadbal/order.py @@ -0,0 +1,107 @@ +"""Order and Cancel LBaaS instances.""" +import click + +import SoftLayer +from SoftLayer.CLI import environment, formatting, helpers, exceptions +from SoftLayer.exceptions import SoftLayerAPIError +from SoftLayer import utils +from pprint import pprint as pp + + + + +@click.command() +@click.argument('identifier') +@environment.pass_env +def order(env, identifier): + """Creates a LB""" + print("Nothing yet") + mgr = SoftLayer.LoadBalancerManager(env.client) + package_name = 'Load Balancer As A Service (LBaaS)' + location = 'MEXICO' + name = 'My-LBaaS-name' + description = 'A description sample' + + # Set False for private network + is_public = True + + protocols = [ + { + "backendPort": 80, + "backendProtocol": "HTTP", + "frontendPort": 8080, + "frontendProtocol": "HTTP", + "loadBalancingMethod": "ROUNDROBIN", # ROUNDROBIN, LEASTCONNECTION, WEIGHTED_RR + "maxConn": 1000 + } + ] + + # remove verify=True to place the order + receipt = lbaas.order_lbaas(package_name, location, name, description, + protocols, public=is_public, verify=True) + + +@click.command() +@click.option('--datacenter', '-d', help="Show only selected datacenter, use shortname (dal13) format.") +@environment.pass_env +def order_options(env, datacenter): + """Prints options for order a LBaaS""" + print("Prints options for ordering") + mgr = SoftLayer.LoadBalancerManager(env.client) + net_mgr = SoftLayer.NetworkManager(env.client) + package = mgr.lbaas_order_options() + + tables = [] + for region in package['regions']: + dc_name = utils.lookup(region, 'location', 'location', 'name') + + # Skip locations if they are not the one requested. + if datacenter and dc_name != datacenter: + continue + this_table = formatting.Table( + ['Prices', 'Private Subnets'], + title="{}: {}".format(region['keyname'], region['description']) + ) + + l_groups = [] + for group in region['location']['location']['groups']: + l_groups.append(group.get('id')) + + # Price lookups + prices = [] + price_table = formatting.KeyValueTable(['KeyName', 'Cost']) + for item in package['items']: + i_price = {'keyName': item['keyName']} + for price in item.get('prices', []): + if not price.get('locationGroupId'): + i_price['default_price'] = price.get('hourlyRecurringFee') + elif price.get('locationGroupId') in l_groups: + i_price['region_price'] = price.get('hourlyRecurringFee') + prices.append(i_price) + for price in prices: + if price.get('region_price'): + price_table.add_row([price.get('keyName'), price.get('region_price')]) + else: + price_table.add_row([price.get('keyName'), price.get('default_price')]) + + # Vlan/Subnet Lookups + mask = "mask[networkVlan,podName,addressSpace]" + subnets = net_mgr.list_subnets(datacenter=dc_name, network_space='PRIVATE', mask=mask) + subnet_table = formatting.KeyValueTable(['Subnet', 'Vlan']) + + for subnet in subnets: + # Only show these types, easier to filter here than in an API call. + if subnet.get('subnetType') != 'PRIMARY' and subnet.get('subnetType') != 'ADDITIONAL_PRIMARY': + continue + space = "{}/{}".format(subnet.get('networkIdentifier'), subnet.get('cidr')) + vlan = "{}.{}".format(subnet['podName'], subnet['networkVlan']['vlanNumber']) + subnet_table.add_row([space, vlan]) + this_table.add_row([price_table, subnet_table]) + + env.fout(this_table) + + +@click.command() +@environment.pass_env +def cancel(env, identifier, **args): + print("Nothing yet") \ No newline at end of file diff --git a/SoftLayer/CLI/loadbal/pools.py b/SoftLayer/CLI/loadbal/pools.py index 7ada89118..b9a11d929 100644 --- a/SoftLayer/CLI/loadbal/pools.py +++ b/SoftLayer/CLI/loadbal/pools.py @@ -160,9 +160,7 @@ def parse_server(ctx, param, values): def l7pool_add(env, identifier, **args): """Adds a new l7 pool - https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_L7Pool/createL7Pool/ - - -S is in : deliminated format to make grouping IP:port:weight a bit easier. + -S is in colon deliminated format to make grouping IP:port:weight a bit easier. """ mgr = SoftLayer.LoadBalancerManager(env.client) @@ -188,11 +186,24 @@ def l7pool_add(env, identifier, **args): } try: - result = mgr.add_lb_l7_pool(uuid, pool_main, pool_members, pool_health, None) - pp(result) + result = mgr.add_lb_l7_pool(uuid, pool_main, pool_members, pool_health, pool_sticky) click.secho("Success", fg='green') except SoftLayerAPIError as e: click.secho("ERROR: {}".format(e.faultString), fg='red') +@click.command() +@click.argument('identifier') +@environment.pass_env +def l7pool_del(env, identifier): + """Deletes the identified pool + + Identifier is L7Pool Id. NOT the UUID + """ + mgr = SoftLayer.LoadBalancerManager(env.client) + try: + result = mgr.del_lb_l7_pool(identifier) + click.secho("Success", fg='green') + except SoftLayerAPIError as e: + click.secho("ERROR: {}".format(e.faultString), fg='red') diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index d637fa866..fb33ee9e2 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -176,6 +176,11 @@ ('loadbal:pool-edit', 'SoftLayer.CLI.loadbal.pools:edit'), ('loadbal:pool-del', 'SoftLayer.CLI.loadbal.pools:delete'), ('loadbal:l7pool-add', 'SoftLayer.CLI.loadbal.pools:l7pool_add'), + ('loadbal:l7pool-del', 'SoftLayer.CLI.loadbal.pools:l7pool_del'), + ('loadbal:order', 'SoftLayer.CLI.loadbal.order:order'), + ('loadbal:order-options', 'SoftLayer.CLI.loadbal.order:order_options'), + ('loadbal:cancel', 'SoftLayer.CLI.loadbal.order:cancel'), + ('loadbal:ns-detail', 'SoftLayer.CLI.loadbal.ns_detail:cli'), ('loadbal:ns-list', 'SoftLayer.CLI.loadbal.ns_list:cli'), diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 6592d0433..0430a179d 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -25,6 +25,7 @@ def __init__(self, client): self.adc = self.client['Network_Application_Delivery_Controller'] # IBM CLoud LB self.lbaas = self.client['Network_LBaaS_LoadBalancer'] + self.package_keyname = 'LBAAS' @@ -154,47 +155,20 @@ def add_lb_l7_pool(self, identifier, pool, members, health, session): :param session SoftLayer_Network_LBaaS_L7SessionAffinity: Weather to use affinity """ - l7Members = [ - { - 'address': '10.131.11.60', - 'port': 82, - 'weight': 10 - }, - { - 'address': '10.131.11.46', - 'port': 83, - 'weight': 11 - } - ] - - l7Pool = { - 'name': 'image112_pool', - 'protocol': 'HTTP', # only supports HTTP - 'loadBalancingAlgorithm': 'ROUNDROBIN' - } - - l7HealthMonitor = { - 'interval': 10, - 'timeout': 5, - 'maxRetries': 3, - 'urlPath': '/' - } - - # Layer 7 session affinity to be added. Only supports SOURCE_IP as of now - l7SessionAffinity = { - 'type': 'SOURCE_IP' - } - - # result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', - # identifier, pool, members, health, session) result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', - identifier, l7Pool, l7Members, l7HealthMonitor, l7SessionAffinity) + identifier, pool, members, health, session) + return result - # string, member, monitor, affinity + def del_lb_l7_pool(self, identifier): + """Deletes a l7 pool + :param identifier: Id of the L7Pool + """ + result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'deleteObject', id=identifier) return result + def remove_lb_listener(self, identifier, listener): """Removes a listener to a LBaaS instance @@ -206,6 +180,53 @@ def remove_lb_listener(self, identifier, listener): identifier, [listener]) return result + def order_lbaas(self, datacenter, name, desc, protocols, subnet_id=None, public=False, verify=False): + """Allows to order a Load Balancer + + + """ + + pkg_name = 'Load Balancer As A Service (LBaaS)' + package_id = self.get_package_id(pkg_name) + prices = self.get_item_prices(package_id) + + # Find and select a subnet id if it was not specified. + if subnet_id is None: + subnet_id = self.get_subnet_id(datacenter) + + # Build the configuration of the order + orderData = { + 'complexType': 'SoftLayer_Container_Product_Order_Network_LoadBalancer_AsAService', + 'name': name, + 'description': desc, + 'location': datacenter, + 'packageId': package_id, + 'useHourlyPricing': True, # Required since LBaaS is an hourly service + 'prices': [{'id': price_id} for price_id in prices], + 'protocolConfigurations': protocols, + 'subnets': [{'id': subnet_id}] + } + + try: + # If verify=True it will check your order for errors. + # It will order the lbaas if False. + if verify: + response = self.client['Product_Order'].verifyOrder(orderData) + else: + response = self.client['Product_Order'].placeOrder(orderData) + + return response + except SoftLayer.SoftLayerAPIError as e: + print("Unable to place the order: %s, %s" % (e.faultCode, e.faultString)) + + + def lbaas_order_options(self): + _filter = {'keyName': {'operation': self.package_keyname}} + mask = "mask[id,keyName,name,items[prices],regions[location[location[groups]]]]" + package = self.client.call('SoftLayer_Product_Package', 'getAllObjects', filter=_filter, mask=mask) + return package.pop() + + # Old things below this line def get_lb_pkgs(self): From c3f363826cf471d0a0065aa5a295a3b4e5251c2a Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 31 Jul 2019 15:24:21 -0500 Subject: [PATCH 07/23] lb ordering done --- SoftLayer/CLI/loadbal/order.py | 76 +++++++++++++++++++++-------- SoftLayer/managers/load_balancer.py | 42 ++++++++-------- 2 files changed, 80 insertions(+), 38 deletions(-) diff --git a/SoftLayer/CLI/loadbal/order.py b/SoftLayer/CLI/loadbal/order.py index 71440063c..f04ab2b68 100644 --- a/SoftLayer/CLI/loadbal/order.py +++ b/SoftLayer/CLI/loadbal/order.py @@ -9,36 +9,74 @@ +def parse_proto(ctx, param, value): + proto = {'protocol': 'HTTP', 'port': 80} + splitout = value.split(':') + if len(splitout) != 2: + raise exceptions.ArgumentError("{}={} is not properly formatted.".format(param, value)) + proto['protocol'] = splitout[0] + proto['port'] = int(splitout[1]) + return proto + + @click.command() -@click.argument('identifier') +@click.option('--name', '-n', help='Label for this loadbalancer.', required=True) +@click.option('--datacenter', '-d', help='Datacenter shortname (dal13).', required=True) +@click.option('--label', '-l', help='A descriptive label for this loadbalancer.') +@click.option('--frontend', '-f', required=True, default='HTTP:80', show_default=True, callback=parse_proto, + help='PROTOCOL:PORT string for incoming internet connections.') +@click.option('--backend', '-b', required=True, default='HTTP:80', show_default=True, callback=parse_proto, + help='PROTOCOL:PORT string for connecting to backend servers.') +@click.option('--method', '-m', help="Balancing Method.", default='ROUNDROBIN', show_default=True, + type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) +@click.option('--subnet', '-s', required=True, + help="Private subnet Id to order the LB on. See `slcli lb order-options`") +@click.option('--public', is_flag=True, default=False, show_default=True, help="Use a Public to Public loadbalancer.") +@click.option('--verify', is_flag=True, default=False, show_default=True, + help="Only verify an order, dont actually create one.") @environment.pass_env -def order(env, identifier): - """Creates a LB""" - print("Nothing yet") +def order(env, **args): + """Creates a LB. Protocols supported are TCP, HTTP, and HTTPS.""" + mgr = SoftLayer.LoadBalancerManager(env.client) - package_name = 'Load Balancer As A Service (LBaaS)' - location = 'MEXICO' - name = 'My-LBaaS-name' - description = 'A description sample' - # Set False for private network - is_public = True + location = args.get('datacenter') + name = args.get('name') + description = args.get('label', None) + + backend = args.get('backend') + frontend = args.get('frontend') protocols = [ { - "backendPort": 80, - "backendProtocol": "HTTP", - "frontendPort": 8080, - "frontendProtocol": "HTTP", - "loadBalancingMethod": "ROUNDROBIN", # ROUNDROBIN, LEASTCONNECTION, WEIGHTED_RR + "backendPort": backend.get('port'), + "backendProtocol": backend.get('protocol'), + "frontendPort": frontend.get('port'), + "frontendProtocol": frontend.get('protocol'), + "loadBalancingMethod": args.get('method'), "maxConn": 1000 } ] # remove verify=True to place the order - receipt = lbaas.order_lbaas(package_name, location, name, description, - protocols, public=is_public, verify=True) + receipt = mgr.order_lbaas(location, name, description, protocols, args.get('subnet'), + public=args.get('public'), verify=args.get('verify')) + table = parse_receipt(receipt) + env.fout(table) + + +def parse_receipt(receipt): + table = formatting.KeyValueTable(['Item', 'Cost'], title="Order: {}".format(receipt.get('orderId', 'Quote'))) + if receipt.get('prices'): + for price in receipt.get('prices'): + table.add_row([price['item']['description'], price['hourlyRecurringFee']]) + elif receipt.get('orderDetails'): + for price in receipt['orderDetails']['prices']: + table.add_row([price['item']['description'], price['hourlyRecurringFee']]) + + return table + @click.command() @@ -87,7 +125,7 @@ def order_options(env, datacenter): # Vlan/Subnet Lookups mask = "mask[networkVlan,podName,addressSpace]" subnets = net_mgr.list_subnets(datacenter=dc_name, network_space='PRIVATE', mask=mask) - subnet_table = formatting.KeyValueTable(['Subnet', 'Vlan']) + subnet_table = formatting.Table(['Id', 'Subnet', 'Vlan']) for subnet in subnets: # Only show these types, easier to filter here than in an API call. @@ -95,7 +133,7 @@ def order_options(env, datacenter): continue space = "{}/{}".format(subnet.get('networkIdentifier'), subnet.get('cidr')) vlan = "{}.{}".format(subnet['podName'], subnet['networkVlan']['vlanNumber']) - subnet_table.add_row([space, vlan]) + subnet_table.add_row([subnet.get('id'), space, vlan]) this_table.add_row([price_table, subnet_table]) env.fout(this_table) diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 0430a179d..4d379385b 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -5,7 +5,9 @@ :license: MIT, see LICENSE for more details. """ +from SoftLayer import exceptions from SoftLayer import utils +from SoftLayer.managers import ordering class LoadBalancerManager(utils.IdentifierMixin, object): @@ -180,19 +182,26 @@ def remove_lb_listener(self, identifier, listener): identifier, [listener]) return result - def order_lbaas(self, datacenter, name, desc, protocols, subnet_id=None, public=False, verify=False): + def order_lbaas(self, datacenter, name, desc, protocols, subnet_id, public=False, verify=False): """Allows to order a Load Balancer - + :param datacenter: Shortname for the SoftLayer datacenter to order in. + :param name: Identifier for the new LB. + :param desc: Optional description for the lb. + :param protocols: https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Listener/ + :param subnet_id: Id of the subnet for this new LB to live on. + :param public: Use Public side for the backend. + :param verify: Don't actually order if True. """ + order_mgr = ordering.OrderingManager(self.client) pkg_name = 'Load Balancer As A Service (LBaaS)' - package_id = self.get_package_id(pkg_name) - prices = self.get_item_prices(package_id) + package = order_mgr.get_package_by_key(self.package_keyname, mask='mask[id,keyName,itemPrices]') - # Find and select a subnet id if it was not specified. - if subnet_id is None: - subnet_id = self.get_subnet_id(datacenter) + prices = [] + for price in package.get('itemPrices'): + if not price.get('locationGroupId', False): + prices.append(price.get('id')) # Build the configuration of the order orderData = { @@ -200,24 +209,19 @@ def order_lbaas(self, datacenter, name, desc, protocols, subnet_id=None, public= 'name': name, 'description': desc, 'location': datacenter, - 'packageId': package_id, + 'packageId': package.get('id'), 'useHourlyPricing': True, # Required since LBaaS is an hourly service 'prices': [{'id': price_id} for price_id in prices], 'protocolConfigurations': protocols, 'subnets': [{'id': subnet_id}] } - try: - # If verify=True it will check your order for errors. - # It will order the lbaas if False. - if verify: - response = self.client['Product_Order'].verifyOrder(orderData) - else: - response = self.client['Product_Order'].placeOrder(orderData) - - return response - except SoftLayer.SoftLayerAPIError as e: - print("Unable to place the order: %s, %s" % (e.faultCode, e.faultString)) + + if verify: + response = self.client['Product_Order'].verifyOrder(orderData) + else: + response = self.client['Product_Order'].placeOrder(orderData) + return response def lbaas_order_options(self): From 9322d60b511bfb6ab00f38a46086d4e081c3edd1 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Thu, 1 Aug 2019 13:08:30 -0500 Subject: [PATCH 08/23] cancel lb support --- SoftLayer/CLI/loadbal/order.py | 15 +- SoftLayer/managers/load_balancer.py | 312 ++-------------------------- 2 files changed, 25 insertions(+), 302 deletions(-) diff --git a/SoftLayer/CLI/loadbal/order.py b/SoftLayer/CLI/loadbal/order.py index f04ab2b68..f2bf028a6 100644 --- a/SoftLayer/CLI/loadbal/order.py +++ b/SoftLayer/CLI/loadbal/order.py @@ -140,6 +140,17 @@ def order_options(env, datacenter): @click.command() +@click.argument('identifier') @environment.pass_env -def cancel(env, identifier, **args): - print("Nothing yet") \ No newline at end of file +def cancel(env, identifier): + """Cancels a LBaaS instance""" + + mgr = SoftLayer.LoadBalancerManager(env.client) + uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + + + try: + result = mgr.cancel_lbaas(uuid) + click.secho("LB {} canceled succesfully.".format(identifier), fg='green') + except SoftLayerAPIError as e: + click.secho("ERROR: {}".format(e.faultString), fg='red') diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 4d379385b..25bb44a71 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -76,7 +76,11 @@ def get_lb(self, identifier, mask=None): lb['health'] = health return lb - def get_lb_monitors(self, identifier, mask=None): + def get_lb_monitors(self, identifier): + """Get a LBaaS instance's health checks + + :param identifier: Id of the LBaaS instance (not UUID) + """ health = self.lbaas.getHealthMonitors(id=identifier) return health @@ -195,7 +199,6 @@ def order_lbaas(self, datacenter, name, desc, protocols, subnet_id, public=False """ order_mgr = ordering.OrderingManager(self.client) - pkg_name = 'Load Balancer As A Service (LBaaS)' package = order_mgr.get_package_by_key(self.package_keyname, mask='mask[id,keyName,itemPrices]') prices = [] @@ -225,309 +228,18 @@ def order_lbaas(self, datacenter, name, desc, protocols, subnet_id, public=False def lbaas_order_options(self): + """Gets the options to order a LBaaS instance.""" _filter = {'keyName': {'operation': self.package_keyname}} mask = "mask[id,keyName,name,items[prices],regions[location[location[groups]]]]" package = self.client.call('SoftLayer_Product_Package', 'getAllObjects', filter=_filter, mask=mask) return package.pop() - -# Old things below this line - - def get_lb_pkgs(self): - """Retrieves the local load balancer packages. - - :returns: A dictionary containing the load balancer packages - """ - - _filter = {'items': {'description': - utils.query_filter('*Load Balancer*')}} - - packages = self.prod_pkg.getItems(id=0, filter=_filter) - pkgs = [] - for package in packages: - if not package['description'].startswith('Global'): - pkgs.append(package) - return pkgs - - def get_hc_types(self): - """Retrieves the health check type values. - - :returns: A dictionary containing the health check types - """ - - svc = self.client['Network_Application_Delivery_Controller_' - 'LoadBalancer_Health_Check_Type'] - return svc.getAllObjects() - - def get_routing_methods(self): - """Retrieves the load balancer routing methods. - - :returns: A dictionary containing the load balancer routing methods - """ - - svc = self.client['Network_Application_Delivery_Controller_' - 'LoadBalancer_Routing_Method'] - return svc.getAllObjects() - - def get_routing_types(self): - """Retrieves the load balancer routing types. - - :returns: A dictionary containing the load balancer routing types - """ - - svc = self.client['Network_Application_Delivery_Controller_' - 'LoadBalancer_Routing_Type'] - return svc.getAllObjects() - - def _get_location(self, datacenter_name): - """Returns the location of the specified datacenter. - - :param string datacenter_name: The datacenter to create - the loadbalancer in - - :returns: the location id of the given datacenter - """ - - datacenters = self.client['Location'].getDataCenters() - for datacenter in datacenters: - if datacenter['name'] == datacenter_name: - return datacenter['id'] - return 'FIRST_AVAILABLE' - - def cancel_lb(self, loadbal_id): - """Cancels the specified load balancer. - - :param int loadbal_id: Load Balancer ID to be cancelled. - """ - - lb_billing = self.lb_svc.getBillingItem(id=loadbal_id) - billing_id = lb_billing['id'] - billing_item = self.client['Billing_Item'] - return billing_item.cancelService(id=billing_id) - - def add_local_lb(self, price_item_id, datacenter): - """Creates a local load balancer in the specified data center. - - :param int price_item_id: The price item ID for the load balancer - :param string datacenter: The datacenter to create the loadbalancer in - :returns: A dictionary containing the product order - """ - - product_order = { - 'complexType': 'SoftLayer_Container_Product_Order_Network_' - 'LoadBalancer', - 'quantity': 1, - 'packageId': 0, - "location": self._get_location(datacenter), - 'prices': [{'id': price_item_id}] - } - return self.client['Product_Order'].placeOrder(product_order) - - - - def get_local_lb(self, loadbal_id, **kwargs): - """Returns a specified local load balancer given the id. - - :param int loadbal_id: The id of the load balancer to retrieve - :returns: A dictionary containing the details of the load balancer - """ - - if 'mask' not in kwargs: - kwargs['mask'] = ('loadBalancerHardware[datacenter], ' - 'ipAddress, virtualServers[serviceGroups' - '[routingMethod,routingType,services' - '[healthChecks[type], groupReferences,' - ' ipAddress]]]') - - return self.lb_svc.getObject(id=loadbal_id, **kwargs) - - def delete_service(self, service_id): - """Deletes a service from the loadbal_id. - - :param int service_id: The id of the service to delete - """ - - svc = self.client['Network_Application_Delivery_Controller_' - 'LoadBalancer_Service'] - - return svc.deleteObject(id=service_id) - - def delete_service_group(self, group_id): - """Deletes a service group from the loadbal_id. - - :param int group_id: The id of the service group to delete - """ - - svc = self.client['Network_Application_Delivery_Controller_' - 'LoadBalancer_VirtualServer'] - - return svc.deleteObject(id=group_id) - - def toggle_service_status(self, service_id): - """Toggles the service status. - - :param int service_id: The id of the service to delete - """ - - svc = self.client['Network_Application_Delivery_Controller_' - 'LoadBalancer_Service'] - return svc.toggleStatus(id=service_id) - - def edit_service(self, loadbal_id, service_id, ip_address_id=None, - port=None, enabled=None, hc_type=None, weight=None): - """Edits an existing service properties. - - :param int loadbal_id: The id of the loadbal where the service resides - :param int service_id: The id of the service to edit - :param string ip_address: The ip address of the service - :param int port: the port of the service - :param bool enabled: enable or disable the search - :param int hc_type: The health check type - :param int weight: the weight to give to the service - """ - - _filter = { - 'virtualServers': { - 'serviceGroups': { - 'services': {'id': utils.query_filter(service_id)}}}} - - mask = 'serviceGroups[services[groupReferences,healthChecks]]' - - virtual_servers = self.lb_svc.getVirtualServers(id=loadbal_id, - filter=_filter, - mask=mask) - - for service in virtual_servers[0]['serviceGroups'][0]['services']: - if service['id'] == service_id: - if enabled is not None: - service['enabled'] = int(enabled) - if port is not None: - service['port'] = port - if weight is not None: - service['groupReferences'][0]['weight'] = weight - if hc_type is not None: - service['healthChecks'][0]['healthCheckTypeId'] = hc_type - if ip_address_id is not None: - service['ipAddressId'] = ip_address_id - - template = {'virtualServers': list(virtual_servers)} - - load_balancer = self.lb_svc.editObject(template, id=loadbal_id) - return load_balancer - - def add_service(self, loadbal_id, service_group_id, ip_address_id, - port=80, enabled=True, hc_type=21, weight=1): - """Adds a new service to the service group. - - :param int loadbal_id: The id of the loadbal where the service resides - :param int service_group_id: The group to add the service to - :param int ip_address id: The ip address ID of the service - :param int port: the port of the service - :param bool enabled: Enable or disable the service - :param int hc_type: The health check type - :param int weight: the weight to give to the service - """ - kwargs = utils.NestedDict({}) - kwargs['mask'] = ('virtualServers[' - 'serviceGroups[services[groupReferences]]]') - - load_balancer = self.lb_svc.getObject(id=loadbal_id, **kwargs) - virtual_servers = load_balancer['virtualServers'] - for virtual_server in virtual_servers: - if virtual_server['id'] == service_group_id: - service_template = { - 'enabled': int(enabled), - 'port': port, - 'ipAddressId': ip_address_id, - 'healthChecks': [ - { - 'healthCheckTypeId': hc_type - } - ], - 'groupReferences': [ - { - 'weight': weight - } - ] - } - services = virtual_server['serviceGroups'][0]['services'] - services.append(service_template) - - return self.lb_svc.editObject(load_balancer, id=loadbal_id) - - def add_service_group(self, lb_id, allocation=100, port=80, - routing_type=2, routing_method=10): - """Adds a new service group to the load balancer. - - :param int loadbal_id: The id of the loadbal where the service resides - :param int allocation: percent of connections to allocate toward the - group - :param int port: the port of the service group - :param int routing_type: the routing type to set on the service group - :param int routing_method: The routing method to set on the group - """ - - mask = 'virtualServers[serviceGroups[services[groupReferences]]]' - load_balancer = self.lb_svc.getObject(id=lb_id, mask=mask) - service_template = { - 'port': port, - 'allocation': allocation, - 'serviceGroups': [ - { - 'routingTypeId': routing_type, - 'routingMethodId': routing_method - } - ] - } - - load_balancer['virtualServers'].append(service_template) - return self.lb_svc.editObject(load_balancer, id=lb_id) - - def edit_service_group(self, loadbal_id, group_id, allocation=None, - port=None, routing_type=None, routing_method=None): - """Edit an existing service group. - - :param int loadbal_id: The id of the loadbal where the service resides - :param int group_id: The id of the service group - :param int allocation: the % of connections to allocate to the group - :param int port: the port of the service group - :param int routing_type: the routing type to set on the service group - :param int routing_method: The routing method to set on the group - """ - - mask = 'virtualServers[serviceGroups[services[groupReferences]]]' - - load_balancer = self.lb_svc.getObject(id=loadbal_id, mask=mask) - virtual_servers = load_balancer['virtualServers'] - - for virtual_server in virtual_servers: - if virtual_server['id'] == group_id: - service_group = virtual_server['serviceGroups'][0] - if allocation is not None: - virtual_server['allocation'] = allocation - if port is not None: - virtual_server['port'] = port - if routing_type is not None: - service_group['routingTypeId'] = routing_type - if routing_method is not None: - service_group['routingMethodId'] = routing_method - break - - return self.lb_svc.editObject(load_balancer, id=loadbal_id) - - def reset_service_group(self, loadbal_id, group_id): - """Resets all the connections on the service group. - - :param int loadbal_id: The id of the loadbal - :param int group_id: The id of the service group to reset + def cancel_lbaas(self, uuid): + """Cancels a LBaaS instance. + + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_LoadBalancer/cancelLoadBalancer/ + :param uuid string: UUID of the LBaaS instance to cancel """ - _filter = {'virtualServers': {'id': utils.query_filter(group_id)}} - virtual_servers = self.lb_svc.getVirtualServers(id=loadbal_id, - filter=_filter, - mask='serviceGroups') - actual_id = virtual_servers[0]['serviceGroups'][0]['id'] + return self.lbaas.cancelLoadBalancer(uuid) - svc = self.client['Network_Application_Delivery_Controller' - '_LoadBalancer_Service_Group'] - return svc.kickAllConnections(id=actual_id) From fe403e1d709231a560b88f858cb96d5a92c8dc98 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Mon, 5 Aug 2019 16:56:45 -0500 Subject: [PATCH 09/23] tox style fixes --- SoftLayer/CLI/loadbal/__init__.py | 1 - SoftLayer/CLI/loadbal/detail.py | 84 ++++++------ SoftLayer/CLI/loadbal/health.py | 17 +-- SoftLayer/CLI/loadbal/list.py | 26 ++-- SoftLayer/CLI/loadbal/members.py | 33 ++--- SoftLayer/CLI/loadbal/ns_detail.py | 27 ++-- SoftLayer/CLI/loadbal/ns_list.py | 9 +- SoftLayer/CLI/loadbal/order.py | 30 ++--- SoftLayer/CLI/loadbal/pools.py | 104 ++++++++------- SoftLayer/managers/load_balancer.py | 57 ++++---- tests/managers/loadbal_tests.py | 196 ---------------------------- 11 files changed, 185 insertions(+), 399 deletions(-) diff --git a/SoftLayer/CLI/loadbal/__init__.py b/SoftLayer/CLI/loadbal/__init__.py index 77d12e33d..9c48549fc 100644 --- a/SoftLayer/CLI/loadbal/__init__.py +++ b/SoftLayer/CLI/loadbal/__init__.py @@ -1,2 +1 @@ """Load balancers.""" - diff --git a/SoftLayer/CLI/loadbal/detail.py b/SoftLayer/CLI/loadbal/detail.py index 545c19cde..eb832d594 100644 --- a/SoftLayer/CLI/loadbal/detail.py +++ b/SoftLayer/CLI/loadbal/detail.py @@ -5,7 +5,7 @@ from SoftLayer.CLI import environment from SoftLayer.CLI import formatting from SoftLayer import utils -from pprint import pprint as pp + @click.command() @click.argument('identifier') @@ -13,67 +13,64 @@ def cli(env, identifier): """Get Load Balancer as a Service details.""" mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) - lb = mgr.get_lb(lbid) - # pp(lb) - if lb.get('previousErrorText'): - print("THERE WAS AN ERROR") - print(lb.get('previousErrorText')) - table = lbaas_table(lb) + _, lbid = mgr.get_lbaas_uuid_id(identifier) + this_lb = mgr.get_lb(lbid) + if this_lb.get('previousErrorText'): + print(this_lb.get('previousErrorText')) + table = lbaas_table(this_lb) env.fout(table) -def lbaas_table(lb): +def lbaas_table(this_lb): """Generates a table from a list of LBaaS devices""" table = formatting.KeyValueTable(['name', 'value']) table.align['name'] = 'r' table.align['value'] = 'l' - table.add_row(['Id', lb.get('id')]) - table.add_row(['UUI', lb.get('uuid')]) - table.add_row(['Address', lb.get('address')]) - table.add_row(['Location', utils.lookup(lb, 'datacenter', 'longName')]) - table.add_row(['Description', lb.get('description')]) - table.add_row(['Name', lb.get('name')]) - table.add_row(['Status', "{} / {}".format(lb.get('provisioningStatus'), lb.get('operatingStatus'))]) + table.add_row(['Id', this_lb.get('id')]) + table.add_row(['UUI', this_lb.get('uuid')]) + table.add_row(['Address', this_lb.get('address')]) + table.add_row(['Location', utils.lookup(this_lb, 'datacenter', 'longName')]) + table.add_row(['Description', this_lb.get('description')]) + table.add_row(['Name', this_lb.get('name')]) + table.add_row(['Status', "{} / {}".format(this_lb.get('provisioningStatus'), this_lb.get('operatingStatus'))]) # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_HealthMonitor/ hp_table = formatting.Table(['UUID', 'Interval', 'Retries', 'Type', 'Timeout', 'Modify', 'Active']) - for hp in lb.get('healthMonitors', []): + for health in this_lb.get('healthMonitors', []): hp_table.add_row([ - hp.get('uuid'), - hp.get('interval'), - hp.get('maxRetries'), - hp.get('monitorType'), - hp.get('timeout'), - utils.clean_time(hp.get('modifyDate')), - hp.get('provisioningStatus') + health.get('uuid'), + health.get('interval'), + health.get('maxRetries'), + health.get('monitorType'), + health.get('timeout'), + utils.clean_time(health.get('modifyDate')), + health.get('provisioningStatus') ]) table.add_row(['Checks', hp_table]) # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7Pool/ - l7_table = formatting.Table(['Id', 'UUID', 'Balancer', 'Name', 'Protocol', 'Modify', 'Active' ]) - for l7 in lb.get('l7Pools', []): + l7_table = formatting.Table(['Id', 'UUID', 'Balancer', 'Name', 'Protocol', 'Modify', 'Active']) + for layer7 in this_lb.get('l7Pools', []): l7_table.add_row([ - l7.get('id'), - l7.get('uuid'), - l7.get('loadBalancingAlgorithm'), - l7.get('name'), - l7.get('protocol'), - utils.clean_time(l7.get('modifyDate')), - l7.get('provisioningStatus') + layer7.get('id'), + layer7.get('uuid'), + layer7.get('loadBalancingAlgorithm'), + layer7.get('name'), + layer7.get('protocol'), + utils.clean_time(layer7.get('modifyDate')), + layer7.get('provisioningStatus') ]) table.add_row(['L7 Pools', l7_table]) pools = {} # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Listener/ listener_table = formatting.Table(['UUID', 'Max Connection', 'Mapping', 'Balancer', 'Modify', 'Active']) - for listener in lb.get('listeners', []): + for listener in this_lb.get('listeners', []): pool = listener.get('defaultPool') priv_map = "{}:{}".format(pool['protocol'], pool['protocolPort']) pools[pool['uuid']] = priv_map mapping = "{}:{} -> {}".format(listener.get('protocol'), listener.get('protocolPort'), priv_map) - pool_table = formatting.Table(['Address', ]) listener_table.add_row([ listener.get('uuid'), listener.get('connectionLimit', 'None'), @@ -86,10 +83,10 @@ def lbaas_table(lb): # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Member/ member_col = ['UUID', 'Address', 'Weight', 'Modify', 'Active'] - for uuid in pools.keys(): + for uuid in pools: member_col.append(pools[uuid]) member_table = formatting.Table(member_col) - for member in lb.get('members', []): + for member in this_lb.get('members', []): row = [ member.get('uuid'), member.get('address'), @@ -97,19 +94,20 @@ def lbaas_table(lb): utils.clean_time(member.get('modifyDate')), member.get('provisioningStatus') ] - for uuid in pools.keys(): - row.append(getMemberHp(lb.get('health'), member.get('uuid'), uuid)) + for uuid in pools: + row.append(get_member_hp(this_lb.get('health'), member.get('uuid'), uuid)) member_table.add_row(row) - table.add_row(['Members',member_table]) + table.add_row(['Members', member_table]) # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_SSLCipher/ ssl_table = formatting.Table(['Id', 'Name']) - for ssl in lb.get('sslCiphers', []): + for ssl in this_lb.get('sslCiphers', []): ssl_table.add_row([ssl.get('id'), ssl.get('name')]) table.add_row(['Ciphers', ssl_table]) return table -def getMemberHp(checks, member_uuid, pool_uuid): + +def get_member_hp(checks, member_uuid, pool_uuid): """Helper function to find a members health in a given pool :param checks list: https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Pool/#healthMonitor @@ -123,4 +121,4 @@ def getMemberHp(checks, member_uuid, pool_uuid): if hp_member.get('uuid') == member_uuid: status = hp_member.get('status') - return status \ No newline at end of file + return status diff --git a/SoftLayer/CLI/loadbal/health.py b/SoftLayer/CLI/loadbal/health.py index d487ee535..19826ea98 100644 --- a/SoftLayer/CLI/loadbal/health.py +++ b/SoftLayer/CLI/loadbal/health.py @@ -4,27 +4,26 @@ import SoftLayer from SoftLayer.CLI import environment from SoftLayer.CLI import exceptions -from SoftLayer.CLI import formatting -from SoftLayer.CLI import helpers from SoftLayer import utils -from pprint import pprint as pp + @click.command() @click.argument('identifier') @click.option('--uuid', required=True, help="Health check UUID to modify.") -@click.option('--interval', '-i', type=click.IntRange(2, 60), help="Seconds between checks. [2-60]") +@click.option('--interval', '-i', type=click.IntRange(2, 60), help="Seconds between checks. [2-60]") @click.option('--retry', '-r', type=click.IntRange(1, 10), help="Number of times before marking as DOWN. [1-10]") @click.option('--timeout', '-t', type=click.IntRange(1, 59), help="Seconds to wait for a connection. [1-59]") @click.option('--url', '-u', help="Url path for HTTP/HTTPS checks.") @environment.pass_env -def cli(env, identifier, uuid, interval, retry, timeout, url): +def cli(env, identifier, uuid, interval, retry, timeout, url): """Manage LBaaS health checks.""" if not any([interval, retry, timeout, url]): raise exceptions.ArgumentError("Specify either interval, retry, timeout, url") # map parameters to expected API names - template = {'healthMonitorUuid': uuid, 'interval': interval, 'maxRetries': retry, 'timeout': timeout, 'urlPath': url} + template = {'healthMonitorUuid': uuid, 'interval': interval, + 'maxRetries': retry, 'timeout': timeout, 'urlPath': url} # Removes those empty values clean_template = {k: v for k, v in template.items() if v is not None} @@ -49,7 +48,6 @@ def cli(env, identifier, uuid, interval, retry, timeout, url): check['timeout'] = utils.lookup(listener, 'defaultPool', 'healthMonitor', 'timeout') check['urlPath'] = utils.lookup(listener, 'defaultPool', 'healthMonitor', 'urlPath') - if url and check['backendProtocol'] == 'TCP': raise exceptions.ArgumentError('--url cannot be used with TCP checks') @@ -57,12 +55,9 @@ def cli(env, identifier, uuid, interval, retry, timeout, url): for key in clean_template.keys(): check[key] = clean_template[key] - result = mgr.updateLoadBalancerHealthMonitors(lb_uuid, [check]) + result = mgr.update_lb_health_monitors(lb_uuid, [check]) if result: click.secho('Health Check {} updated successfully'.format(uuid), fg='green') else: click.secho('ERROR: Failed to update {}'.format(uuid), fg='red') - - - diff --git a/SoftLayer/CLI/loadbal/list.py b/SoftLayer/CLI/loadbal/list.py index 228a98ec6..4eb2f5731 100644 --- a/SoftLayer/CLI/loadbal/list.py +++ b/SoftLayer/CLI/loadbal/list.py @@ -5,7 +5,7 @@ from SoftLayer.CLI import environment from SoftLayer.CLI import formatting from SoftLayer import utils -from pprint import pprint as pp + @click.command() @environment.pass_env @@ -22,9 +22,9 @@ def cli(env): env.fout("No LBaaS devices found") -def location_sort(x): +def location_sort(location): """Quick function that just returns the datacenter longName for sorting""" - return utils.lookup(x, 'datacenter', 'longName') + return utils.lookup(location, 'datacenter', 'longName') def generate_lbaas_table(lbaas): @@ -36,19 +36,17 @@ def generate_lbaas_table(lbaas): table.align['Address'] = 'l' table.align['Description'] = 'l' table.align['Location'] = 'l' - for lb in sorted(lbaas,key=location_sort): - print("PUBLIC: {}".format(lb.get('isPublic'))) + for this_lb in sorted(lbaas, key=location_sort): table.add_row([ - lb.get('id'), - utils.lookup(lb, 'datacenter', 'longName'), - lb.get('address'), - lb.get('description'), - 'Yes' if lb.get('isPublic', 1) == 1 else 'No', - utils.clean_time(lb.get('createDate')), - lb.get('memberCount', 0), - lb.get('listenerCount', 0) + this_lb.get('id'), + utils.lookup(this_lb, 'datacenter', 'longName'), + this_lb.get('address'), + this_lb.get('description'), + 'Yes' if this_lb.get('isPublic', 1) == 1 else 'No', + utils.clean_time(this_lb.get('createDate')), + this_lb.get('memberCount', 0), + this_lb.get('listenerCount', 0) ]) return table - diff --git a/SoftLayer/CLI/loadbal/members.py b/SoftLayer/CLI/loadbal/members.py index 0f0ffe228..bfa81818f 100644 --- a/SoftLayer/CLI/loadbal/members.py +++ b/SoftLayer/CLI/loadbal/members.py @@ -2,16 +2,15 @@ import click import SoftLayer -from SoftLayer.CLI import environment, formatting, helpers +from SoftLayer.CLI import environment from SoftLayer.exceptions import SoftLayerAPIError -from SoftLayer import utils -from pprint import pprint as pp + @click.command() @click.argument('identifier') @click.option('--member', '-m', required=True, help="Member UUID") @environment.pass_env -def remove(env, identifier, member): +def remove(env, identifier, member): """Remove a LBaaS member. Member UUID can be found from `slcli lb detail`. @@ -19,14 +18,14 @@ def remove(env, identifier, member): mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + uuid, _ = mgr.get_lbaas_uuid_id(identifier) # Get a member ID to remove try: - result = mgr.delete_lb_member(uuid, member) + mgr.delete_lb_member(uuid, member) click.secho("Member {} removed".format(member), fg='green') - except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') + except SoftLayerAPIError as exception: + click.secho("ERROR: {}".format(exception.faultString), fg='red') @click.command() @@ -35,11 +34,11 @@ def remove(env, identifier, member): @click.option('--member', '-m', required=True, help="Member IP address.") @click.option('--weight', '-w', default=50, type=int, help="Weight of this member.") @environment.pass_env -def add(env, identifier, private, member, weight): +def add(env, identifier, private, member, weight): """Add a new LBaaS members.""" mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + uuid, _ = mgr.get_lbaas_uuid_id(identifier) # Get a server ID to add to_add = {"weight": weight} if private: @@ -48,15 +47,11 @@ def add(env, identifier, private, member, weight): to_add['publicIpAddress'] = member try: - result = mgr.add_lb_member(uuid, to_add) + mgr.add_lb_member(uuid, to_add) click.secho("Member {} added".format(member), fg='green') - except SoftLayerAPIError as e: - if 'publicIpAddress must be a string' in e.faultString: + except SoftLayerAPIError as exception: + if 'publicIpAddress must be a string' in exception.faultString: click.secho("This LB requires a Public IP address for its members and none was supplied", fg='red') - elif 'privateIpAddress must be a string' in e.faultString: + elif 'privateIpAddress must be a string' in exception.faultString: click.secho("This LB requires a Private IP address for its members and none was supplied", fg='red') - click.secho("ERROR: {}".format(e.faultString), fg='red') - - - - + click.secho("ERROR: {}".format(exception.faultString), fg='red') diff --git a/SoftLayer/CLI/loadbal/ns_detail.py b/SoftLayer/CLI/loadbal/ns_detail.py index 976983b62..537b7c0a4 100644 --- a/SoftLayer/CLI/loadbal/ns_detail.py +++ b/SoftLayer/CLI/loadbal/ns_detail.py @@ -14,25 +14,26 @@ def cli(env, identifier): """Get Netscaler details.""" mgr = SoftLayer.LoadBalancerManager(env.client) - lb = mgr.get_adc(identifier) - table = netscaler_table(lb) + this_lb = mgr.get_adc(identifier) + table = netscaler_table(this_lb) env.fout(table) -def netscaler_table(lb): +def netscaler_table(this_lb): + """Formats the netscaler info table""" table = formatting.KeyValueTable(['name', 'value']) table.align['name'] = 'r' table.align['value'] = 'l' - table.add_row(['Id', lb.get('id')]) - table.add_row(['Type', lb.get('description')]) - table.add_row(['Name', lb.get('name')]) - table.add_row(['Location', utils.lookup(lb, 'datacenter', 'longName')]) - table.add_row(['Managment Ip', lb.get('managementIpAddress')]) - table.add_row(['Root Password', utils.lookup(lb, 'password', 'password')]) - table.add_row(['Primary Ip', lb.get('primaryIpAddress')]) - table.add_row(['License Expiration', utils.clean_time(lb.get('licenseExpirationDate'))]) + table.add_row(['Id', this_lb.get('id')]) + table.add_row(['Type', this_lb.get('description')]) + table.add_row(['Name', this_lb.get('name')]) + table.add_row(['Location', utils.lookup(this_lb, 'datacenter', 'longName')]) + table.add_row(['Managment Ip', this_lb.get('managementIpAddress')]) + table.add_row(['Root Password', utils.lookup(this_lb, 'password', 'password')]) + table.add_row(['Primary Ip', this_lb.get('primaryIpAddress')]) + table.add_row(['License Expiration', utils.clean_time(this_lb.get('licenseExpirationDate'))]) subnet_table = formatting.Table(['Id', 'Subnet', 'Type', 'Space']) - for subnet in lb.get('subnets', []): + for subnet in this_lb.get('subnets', []): subnet_table.add_row([ subnet.get('id'), "{}/{}".format(subnet.get('networkIdentifier'), subnet.get('cidr')), @@ -42,7 +43,7 @@ def netscaler_table(lb): table.add_row(['Subnets', subnet_table]) vlan_table = formatting.Table(['Id', 'Number']) - for vlan in lb.get('networkVlans', []): + for vlan in this_lb.get('networkVlans', []): vlan_table.add_row([vlan.get('id'), vlan.get('vlanNumber')]) table.add_row(['Vlans', vlan_table]) diff --git a/SoftLayer/CLI/loadbal/ns_list.py b/SoftLayer/CLI/loadbal/ns_list.py index dd97a2f7e..a37d8bce2 100644 --- a/SoftLayer/CLI/loadbal/ns_list.py +++ b/SoftLayer/CLI/loadbal/ns_list.py @@ -21,9 +21,10 @@ def cli(env): env.fout("No Netscalers") -def location_sort(x): +def location_sort(location): """Quick function that just returns the datacenter longName for sorting""" - return utils.lookup(x, 'datacenter', 'longName') + return utils.lookup(location, 'datacenter', 'longName') + def generate_netscaler_table(netscalers): """Tales a list of SoftLayer_Network_Application_Delivery_Controller and makes a table""" @@ -38,9 +39,7 @@ def generate_netscaler_table(netscalers): adc.get('description'), adc.get('primaryIpAddress'), adc.get('managementIpAddress'), - adc.get('outboundPublicBandwidthUsage',0), + adc.get('outboundPublicBandwidthUsage', 0), utils.clean_time(adc.get('createDate')) ]) return table - - diff --git a/SoftLayer/CLI/loadbal/order.py b/SoftLayer/CLI/loadbal/order.py index f2bf028a6..2293da8db 100644 --- a/SoftLayer/CLI/loadbal/order.py +++ b/SoftLayer/CLI/loadbal/order.py @@ -2,14 +2,16 @@ import click import SoftLayer -from SoftLayer.CLI import environment, formatting, helpers, exceptions +from SoftLayer.CLI import environment +from SoftLayer.CLI import exceptions +from SoftLayer.CLI import formatting from SoftLayer.exceptions import SoftLayerAPIError from SoftLayer import utils -from pprint import pprint as pp - +# pylint: disable=unused-argument def parse_proto(ctx, param, value): + """Parses the frontend and backend cli options""" proto = {'protocol': 'HTTP', 'port': 80} splitout = value.split(':') if len(splitout) != 2: @@ -19,7 +21,6 @@ def parse_proto(ctx, param, value): return proto - @click.command() @click.option('--name', '-n', help='Label for this loadbalancer.', required=True) @click.option('--datacenter', '-d', help='Datacenter shortname (dal13).', required=True) @@ -45,10 +46,9 @@ def order(env, **args): name = args.get('name') description = args.get('label', None) - backend = args.get('backend') frontend = args.get('frontend') - protocols = [ + protocols = [ { "backendPort": backend.get('port'), "backendProtocol": backend.get('protocol'), @@ -60,13 +60,14 @@ def order(env, **args): ] # remove verify=True to place the order - receipt = mgr.order_lbaas(location, name, description, protocols, args.get('subnet'), + receipt = mgr.order_lbaas(location, name, description, protocols, args.get('subnet'), public=args.get('public'), verify=args.get('verify')) table = parse_receipt(receipt) env.fout(table) - + def parse_receipt(receipt): + """Takes an order receipt and nicely formats it for cli output""" table = formatting.KeyValueTable(['Item', 'Cost'], title="Order: {}".format(receipt.get('orderId', 'Quote'))) if receipt.get('prices'): for price in receipt.get('prices'): @@ -78,7 +79,6 @@ def parse_receipt(receipt): return table - @click.command() @click.option('--datacenter', '-d', help="Show only selected datacenter, use shortname (dal13) format.") @environment.pass_env @@ -89,7 +89,6 @@ def order_options(env, datacenter): net_mgr = SoftLayer.NetworkManager(env.client) package = mgr.lbaas_order_options() - tables = [] for region in package['regions']: dc_name = utils.lookup(region, 'location', 'location', 'name') @@ -136,7 +135,7 @@ def order_options(env, datacenter): subnet_table.add_row([subnet.get('id'), space, vlan]) this_table.add_row([price_table, subnet_table]) - env.fout(this_table) + env.fout(this_table) @click.command() @@ -146,11 +145,10 @@ def cancel(env, identifier): """Cancels a LBaaS instance""" mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) - + uuid, _ = mgr.get_lbaas_uuid_id(identifier) try: - result = mgr.cancel_lbaas(uuid) + mgr.cancel_lbaas(uuid) click.secho("LB {} canceled succesfully.".format(identifier), fg='green') - except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') + except SoftLayerAPIError as exception: + click.secho("ERROR: {}".format(exception.faultString), fg='red') diff --git a/SoftLayer/CLI/loadbal/pools.py b/SoftLayer/CLI/loadbal/pools.py index b9a11d929..b8da27ac9 100644 --- a/SoftLayer/CLI/loadbal/pools.py +++ b/SoftLayer/CLI/loadbal/pools.py @@ -2,36 +2,57 @@ import click import SoftLayer -from SoftLayer.CLI import environment, formatting, helpers, exceptions +from SoftLayer.CLI import environment +from SoftLayer.CLI import exceptions +from SoftLayer.CLI import helpers from SoftLayer.exceptions import SoftLayerAPIError -from SoftLayer import utils -from pprint import pprint as pp +# pylint: disable=unused-argument def sticky_option(ctx, param, value): + """parses sticky cli option""" if value: return 'SOURCE_IP' return None + +def parse_server(ctx, param, values): + """Splits out the IP, Port, Weight from the --server argument for l7pools""" + servers = [] + for server in values: + splitout = server.split(':') + if len(splitout) != 3: + raise exceptions.ArgumentError( + "--server needs a port and a weight. {} improperly formatted".format(server)) + server = { + 'address': splitout[0], + 'port': splitout[1], + 'weight': splitout[2] + } + servers.append(server) + + return servers + + @click.command() @click.argument('identifier') -@click.option('--frontProtocol', '-P', default='HTTP', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), show_default=True, +@click.option('--frontProtocol', '-P', default='HTTP', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), show_default=True, help="Protocol type to use for incoming connections") @click.option('--backProtocol', '-p', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), help="Protocol type to use when connecting to backend servers. Defaults to whatever --frontProtocol is.") -@click.option('--frontPort', '-f', required=True, type=int, help="Internet side port") -@click.option('--backPort', '-b', required=True, type=int, help="Private side port") -@click.option('--method', '-m', default='ROUNDROBIN', show_default=True, help="Balancing Method", +@click.option('--frontPort', '-f', required=True, type=int, help="Internet side port") +@click.option('--backPort', '-b', required=True, type=int, help="Private side port") +@click.option('--method', '-m', default='ROUNDROBIN', show_default=True, help="Balancing Method", type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) @click.option('--connections', '-c', type=int, help="Maximum number of connections to allow.") @click.option('--sticky', '-s', is_flag=True, callback=sticky_option, help="Make sessions sticky based on source_ip.") @click.option('--sslCert', '-x', help="SSL certificate ID. See `slcli ssl list`") @environment.pass_env -def add(env, identifier, **args): +def add(env, identifier, **args): """Adds a listener to the identifier LB""" mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + uuid, _ = mgr.get_lbaas_uuid_id(identifier) new_listener = { 'backendPort': args.get('backport'), @@ -45,10 +66,10 @@ def add(env, identifier, **args): } try: - result = mgr.add_lb_listener(uuid, new_listener) + mgr.add_lb_listener(uuid, new_listener) click.secho("Success", fg='green') - except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') + except SoftLayerAPIError as exception: + click.secho("ERROR: {}".format(exception.faultString), fg='red') @click.command() @@ -58,7 +79,7 @@ def add(env, identifier, **args): help="Protocol type to use for incoming connections") @click.option('--backProtocol', '-p', type=click.Choice(['HTTP', 'HTTPS', 'TCP']), help="Protocol type to use when connecting to backend servers. Defaults to whatever --frontProtocol is.") -@click.option('--frontPort', '-f', type=int, help="Internet side port") +@click.option('--frontPort', '-f', type=int, help="Internet side port") @click.option('--backPort', '-b', type=int, help="Private side port") @click.option('--method', '-m', help="Balancing Method", type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) @@ -67,14 +88,13 @@ def add(env, identifier, **args): @click.option('--sslCert', '-x', help="SSL certificate ID. See `slcli ssl list`") @environment.pass_env def edit(env, identifier, listener, **args): - """Updates a listener's configuration. + """Updates a listener's configuration. LISTENER should be a UUID, and can be found from `slcli lb detail ` """ mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) - + uuid, _ = mgr.get_lbaas_uuid_id(identifier) new_listener = { 'listenerUuid': listener @@ -91,15 +111,15 @@ def edit(env, identifier, listener, **args): 'sslcert': 'tlsCertificateId' } - for arg in args.keys(): + for arg in args: if args[arg]: new_listener[arg_to_option[arg]] = args[arg] try: - result = mgr.add_lb_listener(uuid, new_listener) + mgr.add_lb_listener(uuid, new_listener) click.secho("Success", fg='green') - except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') + except SoftLayerAPIError as exception: + click.secho("ERROR: {}".format(exception.faultString), fg='red') @click.command() @@ -108,33 +128,18 @@ def edit(env, identifier, listener, **args): @environment.pass_env def delete(env, identifier, listener): """Removes the listener from identified LBaaS instance - + LISTENER should be a UUID, and can be found from `slcli lb detail ` """ mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + uuid, _ = mgr.get_lbaas_uuid_id(identifier) try: - result = mgr.remove_lb_listener(uuid, listener) + mgr.remove_lb_listener(uuid, listener) click.secho("Success", fg='green') - except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') + except SoftLayerAPIError as exception: + click.secho("ERROR: {}".format(exception.faultString), fg='red') -def parse_server(ctx, param, values): - """Splits out the IP, Port, Weight from the --server argument for l7pools""" - servers = [] - for server in values: - splitout = server.split(':') - if len(splitout) != 3: - raise exceptions.ArgumentError("--server needs a port and a weight. {} improperly formatted".format(server)) - server = { - 'address': splitout[0], - 'port': splitout[1], - 'weight': splitout[2] - } - servers.append(server) - - return servers @click.command() @click.argument('identifier') @@ -146,7 +151,7 @@ def parse_server(ctx, param, values): show_default=True, help="Protocol type to use for incoming connections") # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7Member/ @helpers.multi_option('--server', '-S', callback=parse_server, required=True, - help="Backend servers that are part of this pool. Format is colon deliminated. " \ + help="Backend servers that are part of this pool. Format is colon deliminated. " "BACKEND_IP:PORT:WEIGHT. eg. 10.0.0.1:80:50") # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_L7HealthMonitor/ @click.option('--healthPath', default='/', show_default=True, help="Health check path.") @@ -164,7 +169,7 @@ def l7pool_add(env, identifier, **args): """ mgr = SoftLayer.LoadBalancerManager(env.client) - uuid, lbid = mgr.get_lbaas_uuid_id(identifier) + uuid, _ = mgr.get_lbaas_uuid_id(identifier) pool_main = { 'name': args.get('name'), @@ -186,11 +191,10 @@ def l7pool_add(env, identifier, **args): } try: - result = mgr.add_lb_l7_pool(uuid, pool_main, pool_members, pool_health, pool_sticky) + mgr.add_lb_l7_pool(uuid, pool_main, pool_members, pool_health, pool_sticky) click.secho("Success", fg='green') - except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') - + except SoftLayerAPIError as exception: + click.secho("ERROR: {}".format(exception.faultString), fg='red') @click.command() @@ -198,12 +202,12 @@ def l7pool_add(env, identifier, **args): @environment.pass_env def l7pool_del(env, identifier): """Deletes the identified pool - + Identifier is L7Pool Id. NOT the UUID """ mgr = SoftLayer.LoadBalancerManager(env.client) try: - result = mgr.del_lb_l7_pool(identifier) + mgr.del_lb_l7_pool(identifier) click.secho("Success", fg='green') - except SoftLayerAPIError as e: - click.secho("ERROR: {}".format(e.faultString), fg='red') + except SoftLayerAPIError as exception: + click.secho("ERROR: {}".format(exception.faultString), fg='red') diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 25bb44a71..f5c0be9e3 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -5,9 +5,8 @@ :license: MIT, see LICENSE for more details. """ -from SoftLayer import exceptions -from SoftLayer import utils from SoftLayer.managers import ordering +from SoftLayer import utils class LoadBalancerManager(utils.IdentifierMixin, object): @@ -29,8 +28,6 @@ def __init__(self, client): self.lbaas = self.client['Network_LBaaS_LoadBalancer'] self.package_keyname = 'LBAAS' - - def get_adcs(self, mask=None): """Returns a list of all netscalers. @@ -57,9 +54,9 @@ def get_lbaas(self, mask=None): """ if mask is None: mask = "mask[datacenter,listenerCount,memberCount]" - lb = self.lbaas.getAllObjects(mask=mask) + this_lb = self.lbaas.getAllObjects(mask=mask) - return lb + return this_lb def get_lb(self, identifier, mask=None): """Returns a IBM Cloud LoadBalancer @@ -69,24 +66,25 @@ def get_lb(self, identifier, mask=None): if mask is None: mask = "mask[healthMonitors, l7Pools, members, sslCiphers, " \ "listeners[defaultPool[healthMonitor, members, sessionAffinity],l7Policies]]" - - lb = self.lbaas.getObject(id=identifier, mask=mask) - health = self.lbaas.getLoadBalancerMemberHealth(lb.get('uuid')) - lb['health'] = health - return lb + this_lb = self.lbaas.getObject(id=identifier, mask=mask) + health = self.lbaas.getLoadBalancerMemberHealth(this_lb.get('uuid')) + + this_lb['health'] = health + return this_lb def get_lb_monitors(self, identifier): """Get a LBaaS instance's health checks - + + :param identifier: Id of the LBaaS instance (not UUID) """ health = self.lbaas.getHealthMonitors(id=identifier) return health - def updateLoadBalancerHealthMonitors(self, uuid, checks): + def update_lb_health_monitors(self, uuid, checks): """calls SoftLayer_Network_LBaaS_HealthMonitor::updateLoadBalancerHealthMonitors() - + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_HealthMonitor/updateLoadBalancerHealthMonitors/ https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_LoadBalancerHealthMonitorConfiguration/ :param uuid: loadBalancerUuid @@ -104,19 +102,19 @@ def get_lbaas_uuid_id(self, identifier): :return (uuid, id): """ if len(identifier) == 36: - lb = self.lbaas.getLoadBalancer(identifier, mask="mask[id,uuid]") + this_lb = self.lbaas.getLoadBalancer(identifier, mask="mask[id,uuid]") else: - lb = self.lbaas.getObject(id=identifier, mask="mask[id,uuid]") - return lb['uuid'], lb['id'] + this_lb = self.lbaas.getObject(id=identifier, mask="mask[id,uuid]") + return this_lb['uuid'], this_lb['id'] def delete_lb_member(self, identifier, member_id): """Removes a member from a LBaaS instance https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_Member/deleteLoadBalancerMembers/ :param identifier: UUID of the LBaaS instance - :param member_id: Member UUID to remove. + :param member_id: Member UUID to remove. """ - result = self.client.call('SoftLayer_Network_LBaaS_Member', 'deleteLoadBalancerMembers', + result = self.client.call('SoftLayer_Network_LBaaS_Member', 'deleteLoadBalancerMembers', identifier, [member_id]) return result @@ -125,10 +123,10 @@ def add_lb_member(self, identifier, member_id): https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_Member/deleteLoadBalancerMembers/ :param identifier: UUID of the LBaaS instance - :param member_id: Member UUID to remove. + :param member_id: Member UUID to remove. """ - result = self.client.call('SoftLayer_Network_LBaaS_Member', 'addLoadBalancerMembers', + result = self.client.call('SoftLayer_Network_LBaaS_Member', 'addLoadBalancerMembers', identifier, [member_id]) return result @@ -174,7 +172,6 @@ def del_lb_l7_pool(self, identifier): result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'deleteObject', id=identifier) return result - def remove_lb_listener(self, identifier, listener): """Removes a listener to a LBaaS instance @@ -207,26 +204,25 @@ def order_lbaas(self, datacenter, name, desc, protocols, subnet_id, public=False prices.append(price.get('id')) # Build the configuration of the order - orderData = { + order_data = { 'complexType': 'SoftLayer_Container_Product_Order_Network_LoadBalancer_AsAService', 'name': name, 'description': desc, 'location': datacenter, 'packageId': package.get('id'), - 'useHourlyPricing': True, # Required since LBaaS is an hourly service + 'useHourlyPricing': True, # Required since LBaaS is an hourly service 'prices': [{'id': price_id} for price_id in prices], 'protocolConfigurations': protocols, - 'subnets': [{'id': subnet_id}] + 'subnets': [{'id': subnet_id}], + 'isPublic': public } - if verify: - response = self.client['Product_Order'].verifyOrder(orderData) + response = self.client['Product_Order'].verifyOrder(order_data) else: - response = self.client['Product_Order'].placeOrder(orderData) + response = self.client['Product_Order'].placeOrder(order_data) return response - def lbaas_order_options(self): """Gets the options to order a LBaaS instance.""" _filter = {'keyName': {'operation': self.package_keyname}} @@ -236,10 +232,9 @@ def lbaas_order_options(self): def cancel_lbaas(self, uuid): """Cancels a LBaaS instance. - + https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_LoadBalancer/cancelLoadBalancer/ :param uuid string: UUID of the LBaaS instance to cancel """ return self.lbaas.cancelLoadBalancer(uuid) - diff --git a/tests/managers/loadbal_tests.py b/tests/managers/loadbal_tests.py index f7fd63910..dab77ea9f 100644 --- a/tests/managers/loadbal_tests.py +++ b/tests/managers/loadbal_tests.py @@ -7,204 +7,8 @@ import SoftLayer from SoftLayer import testing -VIRT_IP_SERVICE = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_VirtualIpAddress') - class LoadBalancerTests(testing.TestCase): def set_up(self): self.lb_mgr = SoftLayer.LoadBalancerManager(self.client) - - def test_get_lb_pkgs(self): - result = self.lb_mgr.get_lb_pkgs() - - self.assertEqual(len(result), 13) - _filter = { - 'items': { - 'description': { - 'operation': '*= Load Balancer' - } - } - } - self.assert_called_with('SoftLayer_Product_Package', 'getItems', - identifier=0, - filter=_filter) - - def test_get_hc_types(self): - result = self.lb_mgr.get_hc_types() - - self.assertEqual(len(result), 6) - service = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_Health_Check_Type') - self.assert_called_with(service, 'getAllObjects') - - def test_get_routing_methods(self): - result = self.lb_mgr.get_routing_methods() - - self.assertEqual(len(result), 12) - service = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_Routing_Method') - self.assert_called_with(service, 'getAllObjects') - - def test_get_location(self): - id1 = self.lb_mgr._get_location('sjc01') - self.assertEqual(id1, 168642) - - id2 = self.lb_mgr._get_location('dal05') - self.assertEqual(id2, 'FIRST_AVAILABLE') - - def test_get_routing_types(self): - result = self.lb_mgr.get_routing_types() - - self.assertEqual(len(result), 6) - service = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_Routing_Type') - self.assert_called_with(service, 'getAllObjects') - - def test_cancel_lb(self): - result = self.lb_mgr.cancel_lb(6327) - - self.assertEqual(result, True) - self.assert_called_with('SoftLayer_Billing_Item', 'cancelService', - identifier=21370814) - - def test_add_local_lb(self): - self.lb_mgr.add_local_lb(6327, 'sjc01') - - args = ({ - 'complexType': 'SoftLayer_Container_Product_Order_Network_' - 'LoadBalancer', - 'quantity': 1, - 'packageId': 0, - "location": 168642, - 'prices': [{'id': 6327}] - },) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder', - args=args) - - def test_get_local_lbs(self): - result = self.lb_mgr.get_local_lbs() - - self.assertEqual(len(result), 0) - mask = 'mask[loadBalancerHardware[datacenter],ipAddress]' - self.assert_called_with('SoftLayer_Account', 'getAdcLoadBalancers', - mask=mask) - - def test_get_local_lb(self): - result = self.lb_mgr.get_local_lb(22348) - - self.assertEqual(result['id'], 22348) - mask = ('mask[' - 'loadBalancerHardware[datacenter], ' - 'ipAddress, virtualServers[serviceGroups' - '[routingMethod,routingType,services' - '[healthChecks[type], groupReferences,' - ' ipAddress]]]]') - self.assert_called_with(VIRT_IP_SERVICE, 'getObject', - identifier=22348, - mask=mask) - - def test_delete_service(self): - result = self.lb_mgr.delete_service(1234) - - self.assertEqual(result, True) - service = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_Service') - self.assert_called_with(service, 'deleteObject', identifier=1234) - - def test_delete_service_group(self): - result = self.lb_mgr.delete_service_group(1234) - - self.assertEqual(result, True) - service = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_VirtualServer') - self.assert_called_with(service, 'deleteObject', identifier=1234) - - def test_toggle_service_status(self): - result = self.lb_mgr.toggle_service_status(1234) - - self.assertEqual(result, True) - service = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_Service') - self.assert_called_with(service, 'toggleStatus', identifier=1234) - - def test_edit_service(self): - self.lb_mgr.edit_service(12345, 1234, '9.9.9.9', 80, True, 21, 1) - - _filter = { - 'virtualServers': { - 'serviceGroups': { - 'services': { - 'id': { - 'operation': 1234 - } - } - } - } - } - mask = 'mask[serviceGroups[services[groupReferences,healthChecks]]]' - self.assert_called_with(VIRT_IP_SERVICE, 'getVirtualServers', - identifier=12345, - filter=_filter, - mask=mask) - - self.assert_called_with(VIRT_IP_SERVICE, 'editObject') - - def test_add_service(self): - self.lb_mgr.add_service(12345, 50718, 123, 80, True, 21, 1) - - mask = 'mask[virtualServers[serviceGroups[services[groupReferences]]]]' - self.assert_called_with(VIRT_IP_SERVICE, 'getObject', - mask=mask, - identifier=12345) - - self.assert_called_with(VIRT_IP_SERVICE, 'editObject', - identifier=12345) - arg = self.calls(VIRT_IP_SERVICE, 'editObject')[0].args[0] - self.assertEqual( - len(arg['virtualServers'][0]['serviceGroups'][0]['services']), - 2) - - def test_edit_service_group(self): - self.lb_mgr.edit_service_group(12345, - group_id=50718, - allocation=100, - port=80, - routing_type=2, - routing_method=10) - - mask = 'mask[virtualServers[serviceGroups[services[groupReferences]]]]' - self.assert_called_with(VIRT_IP_SERVICE, 'getObject', - identifier=12345, - mask=mask) - - self.assert_called_with(VIRT_IP_SERVICE, 'getObject', identifier=12345) - - def test_add_service_group(self): - self.lb_mgr.add_service_group(12345, 100, 80, 2, 10) - - mask = 'mask[virtualServers[serviceGroups[services[groupReferences]]]]' - self.assert_called_with(VIRT_IP_SERVICE, 'getObject', - mask=mask, - identifier=12345) - - self.assert_called_with(VIRT_IP_SERVICE, 'editObject', - identifier=12345) - arg = self.calls(VIRT_IP_SERVICE, 'editObject')[0].args[0] - self.assertEqual(len(arg['virtualServers']), 2) - - def test_reset_service_group(self): - result = self.lb_mgr.reset_service_group(12345, group_id=50718) - - self.assertEqual(result, True) - _filter = {'virtualServers': {'id': {'operation': 50718}}} - self.assert_called_with(VIRT_IP_SERVICE, 'getVirtualServers', - identifier=12345, - filter=_filter, - mask='mask[serviceGroups]') - - service = ('SoftLayer_Network_Application_Delivery_Controller_' - 'LoadBalancer_Service_Group') - self.assert_called_with(service, 'kickAllConnections', - identifier=51758) From c9bb5f0875fd64e00da83b5e7d5ee0ba2c0d0173 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Thu, 15 Aug 2019 17:22:29 -0500 Subject: [PATCH 10/23] unit tests for lb-manager --- SoftLayer/fixtures/SoftLayer_Account.py | 27 +++++++++++++ ...Network_Application_Delivery_Controller.py | 24 +++++++++++ .../SoftLayer_Network_LBaaS_LoadBalancer.py | 39 ++++++++++++++++++ SoftLayer/managers/load_balancer.py | 9 ----- tests/managers/loadbal_tests.py | 40 +++++++++++++++++++ 5 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py create mode 100644 SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py diff --git a/SoftLayer/fixtures/SoftLayer_Account.py b/SoftLayer/fixtures/SoftLayer_Account.py index cf884aefd..1c8800628 100644 --- a/SoftLayer/fixtures/SoftLayer_Account.py +++ b/SoftLayer/fixtures/SoftLayer_Account.py @@ -715,3 +715,30 @@ 'endingBalance': '12345.55' } ] + +getApplicationDeliveryControllers = [ + { + 'accountId': 307608, + 'createDate': '2015-05-05T16:23:52-06:00', + 'id': 11449, + 'modifyDate': '2015-05-05T16:24:09-06:00', + 'name': 'SLADC307608-1', + 'typeId': 2, + 'description': 'Citrix NetScaler VPX 10.5 10Mbps Standard', + 'managementIpAddress': '10.11.11.112', + 'outboundPublicBandwidthUsage': '.00365', + 'primaryIpAddress': '19.4.24.16', + 'datacenter': { + 'longName': 'Dallas 9', + 'name': 'dal09', + }, + 'password': { + 'password': 'aaaaa', + 'username': 'root' + }, + 'type': { + 'keyName': 'NETSCALER_VPX', + 'name': 'NetScaler VPX' + } + } +] diff --git a/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py new file mode 100644 index 000000000..5316e4466 --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py @@ -0,0 +1,24 @@ +getObject = { + 'accountId': 307608, + 'createDate': '2015-05-05T16:23:52-06:00', + 'id': 11449, + 'modifyDate': '2015-05-05T16:24:09-06:00', + 'name': 'SLADC307608-1', + 'typeId': 2, + 'description': 'Citrix NetScaler VPX 10.5 10Mbps Standard', + 'managementIpAddress': '10.11.11.112', + 'outboundPublicBandwidthUsage': '.00365', + 'primaryIpAddress': '19.4.24.16', + 'datacenter': { + 'longName': 'Dallas 9', + 'name': 'dal09', + }, + 'password': { + 'password': 'aaaaa', + 'username': 'root' + }, + 'type': { + 'keyName': 'NETSCALER_VPX', + 'name': 'NetScaler VPX' + } +} \ No newline at end of file diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py new file mode 100644 index 000000000..717a1746d --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py @@ -0,0 +1,39 @@ +getObject = { + 'accountId': 1234, + 'address': '01-307608-ams01.clb.appdomain.cloud', + 'createDate': '2019-08-12T07:49:43-06:00', + 'id': 1111111, + 'isPublic': 0, + 'locationId': 265592, + 'modifyDate': '2019-08-13T16:26:06-06:00', + 'name': 'dcabero-01', + 'operatingStatus': 'ONLINE', + 'provisioningStatus': 'ACTIVE', + 'type': 0, + 'useSystemPublicIpPool': 1, + 'uuid': '1a1aa111-4474-4e16-9f02-4de959229b85', + 'listenerCount': 4, + 'memberCount': 1, + 'datacenter': { + 'id': 265592, + 'longName': 'Amsterdam 1', + 'name': 'ams01', + 'statusId': 2 + } + } +getAllObjects = [getObject] + + +getLoadBalancerMemberHealth = [ + { + 'poolUuid': '1c5f3ba6-ec7d-4cf8-8815-9bb174224a76', + 'membersHealth': [ + { + 'status': 'DOWN', + 'uuid': 'ba23a166-faa4-4eb2-96e7-ef049d65ce60' + } + ] + } +] + +getHealthMonitors = {} \ No newline at end of file diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index f5c0be9e3..69c1034b0 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -73,15 +73,6 @@ def get_lb(self, identifier, mask=None): this_lb['health'] = health return this_lb - def get_lb_monitors(self, identifier): - """Get a LBaaS instance's health checks - - - :param identifier: Id of the LBaaS instance (not UUID) - """ - health = self.lbaas.getHealthMonitors(id=identifier) - return health - def update_lb_health_monitors(self, uuid, checks): """calls SoftLayer_Network_LBaaS_HealthMonitor::updateLoadBalancerHealthMonitors() diff --git a/tests/managers/loadbal_tests.py b/tests/managers/loadbal_tests.py index dab77ea9f..873eb57e0 100644 --- a/tests/managers/loadbal_tests.py +++ b/tests/managers/loadbal_tests.py @@ -12,3 +12,43 @@ class LoadBalancerTests(testing.TestCase): def set_up(self): self.lb_mgr = SoftLayer.LoadBalancerManager(self.client) + + def test_get_adcs(self): + self.lb_mgr.get_adcs() + self.assert_called_with('SoftLayer_Account', 'getApplicationDeliveryControllers') + + def test_get_adc_masks(self): + self.lb_mgr.get_adcs(mask="mask[id]") + self.assert_called_with('SoftLayer_Account', 'getApplicationDeliveryControllers', mask="mask[id]") + + def test_get_adc(self): + self.lb_mgr.get_adc(1234) + self.assert_called_with('SoftLayer_Network_Application_Delivery_Controller', 'getObject', identifier=1234) + + def test_get_adc_mask(self): + self.lb_mgr.get_adc(1234, mask="mask[id]") + self.assert_called_with('SoftLayer_Network_Application_Delivery_Controller', 'getObject', identifier=1234, + mask="mask[id]") + + def test_get_lbaas(self): + self.lb_mgr.get_lbaas() + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getAllObjects') + + def test_get_lbaas_mask(self): + self.lb_mgr.get_lbaas(mask="mask[id]") + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getAllObjects', mask="mask[id]") + + def test_get_lb(self): + lb = self.lb_mgr.get_lb(1234) + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getObject', identifier=1234) + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getLoadBalancerMemberHealth', + args=(lb.get('uuid'),)) + self.assertIsNotNone(lb['health']) + + def test_get_lb_mask(self): + lb = self.lb_mgr.get_lb(1234, mask="mask[id]") + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getObject', identifier=1234, mask="mask[id]") + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getLoadBalancerMemberHealth', + args=(lb.get('uuid'),)) + self.assertIsNotNone(lb['health']) + From bbac83a6b53303fa12695beb40da749100944aa4 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Mon, 19 Aug 2019 17:17:05 -0500 Subject: [PATCH 11/23] #1158 lb manager unit tests --- .../SoftLayer_Network_LBaaS_HealthMonitor.py | 9 ++ .../SoftLayer_Network_LBaaS_L7Pool.py | 2 + .../SoftLayer_Network_LBaaS_Listener.py | 3 + .../SoftLayer_Network_LBaaS_LoadBalancer.py | 5 +- .../SoftLayer_Network_LBaaS_Member.py | 3 + SoftLayer/managers/load_balancer.py | 39 ++++---- tests/managers/loadbal_tests.py | 92 +++++++++++++++++++ 7 files changed, 130 insertions(+), 23 deletions(-) create mode 100644 SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py create mode 100644 SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py create mode 100644 SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py create mode 100644 SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py new file mode 100644 index 000000000..d3b8770e4 --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py @@ -0,0 +1,9 @@ +updateLoadBalancerHealthMonitors = { + 'backendPort': 80, + 'backendProtocol': 'HTTP', + 'healthMonitorUuid': '1a1aa111-4474-4e16-9f02-4de959244444', + 'interval': 50, + 'maxRetries': 10, + 'timeout': 10, + 'urlPath': None +} \ No newline at end of file diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py new file mode 100644 index 000000000..b3a909a3d --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py @@ -0,0 +1,2 @@ +createL7Pool = {} +deleteObject = {} \ No newline at end of file diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py new file mode 100644 index 000000000..d3954ce29 --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py @@ -0,0 +1,3 @@ +# https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Listener/ +updateLoadBalancerProtocols = {} +deleteLoadBalancerProtocols = {} \ No newline at end of file diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py index 717a1746d..53ffd6749 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py @@ -36,4 +36,7 @@ } ] -getHealthMonitors = {} \ No newline at end of file +getHealthMonitors = {} + +getLoadBalancer = getObject +cancelLoadBalancer = getObject \ No newline at end of file diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py new file mode 100644 index 000000000..9bc95f2cc --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py @@ -0,0 +1,3 @@ +#Should be sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_LoadBalancer +deleteLoadBalancerMembers = {} +addLoadBalancerMembers = deleteLoadBalancerMembers \ No newline at end of file diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 69c1034b0..5bdc419c5 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -92,7 +92,8 @@ def get_lbaas_uuid_id(self, identifier): :param identifier: either the LB Id, or UUID, this function will return both. :return (uuid, id): """ - if len(identifier) == 36: + # int objects don't have a len property. + if not isinstance(identifier, int) and len(identifier) == 36: this_lb = self.lbaas.getLoadBalancer(identifier, mask="mask[id,uuid]") else: this_lb = self.lbaas.getObject(id=identifier, mask="mask[id,uuid]") @@ -105,22 +106,21 @@ def delete_lb_member(self, identifier, member_id): :param identifier: UUID of the LBaaS instance :param member_id: Member UUID to remove. """ - result = self.client.call('SoftLayer_Network_LBaaS_Member', 'deleteLoadBalancerMembers', - identifier, [member_id]) - return result + return self.client.call('SoftLayer_Network_LBaaS_Member', 'deleteLoadBalancerMembers', + identifier, [member_id]) - def add_lb_member(self, identifier, member_id): - """Removes a member from a LBaaS instance + + def add_lb_member(self, identifier, service_info): + """Adds a member to a LBaaS instance https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_Member/deleteLoadBalancerMembers/ :param identifier: UUID of the LBaaS instance - :param member_id: Member UUID to remove. + :param service_info: datatypes/SoftLayer_Network_LBaaS_LoadBalancerServerInstanceInfo """ - result = self.client.call('SoftLayer_Network_LBaaS_Member', 'addLoadBalancerMembers', - identifier, [member_id]) + return self.client.call('SoftLayer_Network_LBaaS_Member', 'addLoadBalancerMembers', + identifier, [service_info]) - return result def add_lb_listener(self, identifier, listener): """Adds or update a listener to a LBaaS instance @@ -133,9 +133,8 @@ def add_lb_listener(self, identifier, listener): :param listener: Object with all listener configurations """ - result = self.client.call('SoftLayer_Network_LBaaS_Listener', 'updateLoadBalancerProtocols', - identifier, [listener]) - return result + return self.client.call('SoftLayer_Network_LBaaS_Listener', 'updateLoadBalancerProtocols', + identifier, [listener]) def add_lb_l7_pool(self, identifier, pool, members, health, session): """Creates a new l7 pool for a LBaaS instance @@ -150,18 +149,15 @@ def add_lb_l7_pool(self, identifier, pool, members, health, session): :param session SoftLayer_Network_LBaaS_L7SessionAffinity: Weather to use affinity """ - result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', - identifier, pool, members, health, session) - - return result + return self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', + identifier, pool, members, health, session) def del_lb_l7_pool(self, identifier): """Deletes a l7 pool :param identifier: Id of the L7Pool """ - result = self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'deleteObject', id=identifier) - return result + return self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'deleteObject', id=identifier) def remove_lb_listener(self, identifier, listener): """Removes a listener to a LBaaS instance @@ -170,9 +166,8 @@ def remove_lb_listener(self, identifier, listener): :param listener: UUID of the Listner to be removed. """ - result = self.client.call('SoftLayer_Network_LBaaS_Listener', 'deleteLoadBalancerProtocols', - identifier, [listener]) - return result + return self.client.call('SoftLayer_Network_LBaaS_Listener', 'deleteLoadBalancerProtocols', + identifier, [listener]) def order_lbaas(self, datacenter, name, desc, protocols, subnet_id, public=False, verify=False): """Allows to order a Load Balancer diff --git a/tests/managers/loadbal_tests.py b/tests/managers/loadbal_tests.py index 873eb57e0..87970b3c2 100644 --- a/tests/managers/loadbal_tests.py +++ b/tests/managers/loadbal_tests.py @@ -3,6 +3,9 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :license: MIT, see LICENSE for more details. + + A lot of these tests will use junk data because the manager just passes + them directly to the API. """ import SoftLayer from SoftLayer import testing @@ -52,3 +55,92 @@ def test_get_lb_mask(self): args=(lb.get('uuid'),)) self.assertIsNotNone(lb['health']) + def test_updated_lb_health(self): + uuid = '1234' + check = {'backendPort': '80'} + self.lb_mgr.update_lb_health_monitors(uuid, check) + self.assert_called_with('SoftLayer_Network_LBaaS_HealthMonitor', 'updateLoadBalancerHealthMonitors', + args=(uuid, check)) + + def test_get_lbaas_uuid_id_uuid(self): + uuid = '1a1aa111-4474-4e16-9f02-4de959229b85' + my_id = 1111111 + lb_uuid,lb_id = self.lb_mgr.get_lbaas_uuid_id(uuid) + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getLoadBalancer', args=(uuid,)) + self.assertEqual(lb_uuid, uuid) + self.assertEqual(lb_id, my_id) + + def test_get_lbaas_uuid_id_id(self): + uuid = '1a1aa111-4474-4e16-9f02-4de959229b85' + my_id = 1111111 + lb_uuid,lb_id = self.lb_mgr.get_lbaas_uuid_id(my_id) + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getObject', identifier=my_id) + self.assertEqual(lb_uuid, uuid) + self.assertEqual(lb_id, my_id) + + def test_delete_lb_member(self): + uuid = 'aa-bb-cc' + member_id = 'dd-ee-ff' + self.lb_mgr.delete_lb_member(uuid, member_id) + self.assert_called_with('SoftLayer_Network_LBaaS_Member', 'deleteLoadBalancerMembers', + args=(uuid, [member_id])) + + def test_add_lb_member(self): + uuid = 'aa-bb-cc' + member = {'privateIpAddress': '1.2.3.4'} + self.lb_mgr.add_lb_member(uuid, member) + self.assert_called_with('SoftLayer_Network_LBaaS_Member', 'addLoadBalancerMembers', + args=(uuid, [member])) + + def test_add_lb_listener(self): + uuid = 'aa-bb-cc' + listener = {'id': 1} + self.lb_mgr.add_lb_listener(uuid, listener) + self.assert_called_with('SoftLayer_Network_LBaaS_Listener', 'updateLoadBalancerProtocols', + args=(uuid, [listener])) + + def test_add_lb_l7_pool(self): + uuid = 'aa-bb-cc' + pool = {'id': 1} + members = {'id': 1} + health = {'id': 1} + session = {'id': 1} + self.lb_mgr.add_lb_l7_pool(uuid, pool, members, health, session) + self.assert_called_with('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', + args=(uuid, pool, members, health, session)) + + def test_del_lb_l7_pool(self): + uuid = 'aa-bb-cc' + self.lb_mgr.del_lb_l7_pool(uuid) + self.assert_called_with('SoftLayer_Network_LBaaS_L7Pool', 'deleteObject', identifier=uuid) + + def test_remove_lb_listener(self): + uuid = 'aa-bb-cc' + listener = 'dd-ee-ff' + self.lb_mgr.remove_lb_listener(uuid, listener) + self.assert_called_with('SoftLayer_Network_LBaaS_Listener', 'deleteLoadBalancerProtocols', + args=(uuid, [listener])) + + def order_lbaas(self): + datacenter = 'tes01' + name = 'test-lb' + desc = 'my lb' + protocols = {'frontendPort': 80, 'frontendProtocol': 'HTTP'} + subnet_id = 12345 + public = True + verify = False + self.lb_mgr.order_lbaas(datacenter, name, desc, protocols, subnet_id, public, verify) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + verify = True + self.lb_mgr.order_lbaas(datacenter, name, desc, protocols, subnet_id, public, verify) + self.assert_called_with('SoftLayer_Product_Order', 'verifyOrder') + + def test_lbaas_order_options(self): + self.lb_mgr.lbaas_order_options() + self.assert_called_with('SoftLayer_Product_Package', 'getAllObjects') + + def test_cancel_lbaas(self): + uuid = 'aa-bb-cc' + self.lb_mgr.cancel_lbaas(uuid) + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'cancelLoadBalancer', args=(uuid,)) + From 22497240b40ddeffff62ddd58f0de8c2acae381b Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Mon, 19 Aug 2019 17:43:39 -0500 Subject: [PATCH 12/23] #1158 tox style fixes --- ...Network_Application_Delivery_Controller.py | 2 +- .../SoftLayer_Network_LBaaS_HealthMonitor.py | 2 +- .../SoftLayer_Network_LBaaS_L7Pool.py | 2 +- .../SoftLayer_Network_LBaaS_Listener.py | 2 +- .../SoftLayer_Network_LBaaS_LoadBalancer.py | 4 +- .../SoftLayer_Network_LBaaS_Member.py | 4 +- SoftLayer/managers/load_balancer.py | 12 +++--- tests/managers/loadbal_tests.py | 42 ++++++++++++++++--- 8 files changed, 50 insertions(+), 20 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py index 5316e4466..532968d50 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py +++ b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py @@ -21,4 +21,4 @@ 'keyName': 'NETSCALER_VPX', 'name': 'NetScaler VPX' } -} \ No newline at end of file +} diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py index d3b8770e4..74696c7f5 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_HealthMonitor.py @@ -6,4 +6,4 @@ 'maxRetries': 10, 'timeout': 10, 'urlPath': None -} \ No newline at end of file +} diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py index b3a909a3d..2d66fcd5c 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py @@ -1,2 +1,2 @@ createL7Pool = {} -deleteObject = {} \ No newline at end of file +deleteObject = {} diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py index d3954ce29..5af3844e1 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py @@ -1,3 +1,3 @@ # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Listener/ updateLoadBalancerProtocols = {} -deleteLoadBalancerProtocols = {} \ No newline at end of file +deleteLoadBalancerProtocols = {} diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py index 53ffd6749..d9dcce0ca 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py @@ -1,4 +1,4 @@ -getObject = { +getObject = { 'accountId': 1234, 'address': '01-307608-ams01.clb.appdomain.cloud', 'createDate': '2019-08-12T07:49:43-06:00', @@ -39,4 +39,4 @@ getHealthMonitors = {} getLoadBalancer = getObject -cancelLoadBalancer = getObject \ No newline at end of file +cancelLoadBalancer = getObject diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py index 9bc95f2cc..449b52a67 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Member.py @@ -1,3 +1,3 @@ -#Should be sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_LoadBalancer +# Should be sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_LoadBalancer deleteLoadBalancerMembers = {} -addLoadBalancerMembers = deleteLoadBalancerMembers \ No newline at end of file +addLoadBalancerMembers = deleteLoadBalancerMembers diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 5bdc419c5..072077ef0 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -107,8 +107,7 @@ def delete_lb_member(self, identifier, member_id): :param member_id: Member UUID to remove. """ return self.client.call('SoftLayer_Network_LBaaS_Member', 'deleteLoadBalancerMembers', - identifier, [member_id]) - + identifier, [member_id]) def add_lb_member(self, identifier, service_info): """Adds a member to a LBaaS instance @@ -119,8 +118,7 @@ def add_lb_member(self, identifier, service_info): """ return self.client.call('SoftLayer_Network_LBaaS_Member', 'addLoadBalancerMembers', - identifier, [service_info]) - + identifier, [service_info]) def add_lb_listener(self, identifier, listener): """Adds or update a listener to a LBaaS instance @@ -134,7 +132,7 @@ def add_lb_listener(self, identifier, listener): """ return self.client.call('SoftLayer_Network_LBaaS_Listener', 'updateLoadBalancerProtocols', - identifier, [listener]) + identifier, [listener]) def add_lb_l7_pool(self, identifier, pool, members, health, session): """Creates a new l7 pool for a LBaaS instance @@ -150,7 +148,7 @@ def add_lb_l7_pool(self, identifier, pool, members, health, session): """ return self.client.call('SoftLayer_Network_LBaaS_L7Pool', 'createL7Pool', - identifier, pool, members, health, session) + identifier, pool, members, health, session) def del_lb_l7_pool(self, identifier): """Deletes a l7 pool @@ -167,7 +165,7 @@ def remove_lb_listener(self, identifier, listener): """ return self.client.call('SoftLayer_Network_LBaaS_Listener', 'deleteLoadBalancerProtocols', - identifier, [listener]) + identifier, [listener]) def order_lbaas(self, datacenter, name, desc, protocols, subnet_id, public=False, verify=False): """Allows to order a Load Balancer diff --git a/tests/managers/loadbal_tests.py b/tests/managers/loadbal_tests.py index 87970b3c2..cf93ed9a6 100644 --- a/tests/managers/loadbal_tests.py +++ b/tests/managers/loadbal_tests.py @@ -65,7 +65,7 @@ def test_updated_lb_health(self): def test_get_lbaas_uuid_id_uuid(self): uuid = '1a1aa111-4474-4e16-9f02-4de959229b85' my_id = 1111111 - lb_uuid,lb_id = self.lb_mgr.get_lbaas_uuid_id(uuid) + lb_uuid, lb_id = self.lb_mgr.get_lbaas_uuid_id(uuid) self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getLoadBalancer', args=(uuid,)) self.assertEqual(lb_uuid, uuid) self.assertEqual(lb_id, my_id) @@ -73,7 +73,7 @@ def test_get_lbaas_uuid_id_uuid(self): def test_get_lbaas_uuid_id_id(self): uuid = '1a1aa111-4474-4e16-9f02-4de959229b85' my_id = 1111111 - lb_uuid,lb_id = self.lb_mgr.get_lbaas_uuid_id(my_id) + lb_uuid, lb_id = self.lb_mgr.get_lbaas_uuid_id(my_id) self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'getObject', identifier=my_id) self.assertEqual(lb_uuid, uuid) self.assertEqual(lb_id, my_id) @@ -121,7 +121,7 @@ def test_remove_lb_listener(self): self.assert_called_with('SoftLayer_Network_LBaaS_Listener', 'deleteLoadBalancerProtocols', args=(uuid, [listener])) - def order_lbaas(self): + def test_order_lbaas(self): datacenter = 'tes01' name = 'test-lb' desc = 'my lb' @@ -129,8 +129,41 @@ def order_lbaas(self): subnet_id = 12345 public = True verify = False + package = [ + { + 'id': 805, + 'keyNake': 'LBAAS', + 'itemPrices': [ + { + 'id': 1, + 'name': 'A test price', + 'locationGroupId': None + }, + { + 'id': 2, + 'name': 'A test price 2', + 'locationGroupId': 123 + } + ] + } + ] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = package + order_data = { + 'complexType': 'SoftLayer_Container_Product_Order_Network_LoadBalancer_AsAService', + 'name': name, + 'description': desc, + 'location': datacenter, + 'packageId': package[0]['id'], + 'useHourlyPricing': True, # Required since LBaaS is an hourly service + 'prices': [{'id': package[0]['itemPrices'][0]['id']}], + 'protocolConfigurations': protocols, + 'subnets': [{'id': subnet_id}], + 'isPublic': public + } self.lb_mgr.order_lbaas(datacenter, name, desc, protocols, subnet_id, public, verify) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder', args=(order_data,)) + self.assert_called_with('SoftLayer_Product_Package', 'getAllObjects') verify = True self.lb_mgr.order_lbaas(datacenter, name, desc, protocols, subnet_id, public, verify) self.assert_called_with('SoftLayer_Product_Order', 'verifyOrder') @@ -143,4 +176,3 @@ def test_cancel_lbaas(self): uuid = 'aa-bb-cc' self.lb_mgr.cancel_lbaas(uuid) self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'cancelLoadBalancer', args=(uuid,)) - From 4219b23239cb6b0e07551e496db5c7db403ed71e Mon Sep 17 00:00:00 2001 From: Daniel Cabero Barrios Date: Fri, 23 Aug 2019 18:07:56 -0400 Subject: [PATCH 13/23] unit test lodabalancer List.py, pool.py --- tests/CLI/modules/loadbal_tests.py | 121 +++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 tests/CLI/modules/loadbal_tests.py diff --git a/tests/CLI/modules/loadbal_tests.py b/tests/CLI/modules/loadbal_tests.py new file mode 100644 index 000000000..26505fcc8 --- /dev/null +++ b/tests/CLI/modules/loadbal_tests.py @@ -0,0 +1,121 @@ +""" + SoftLayer.tests.managers.loadbal_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. +""" +from mock import mock + +import SoftLayer +from SoftLayer import testing +from SoftLayer.CLI.exceptions import ArgumentError + + +class LoadBalancerTests(testing.TestCase): + + def test_cli_list(self): + result = self.run_command(['loadbal', 'list']) + self.assert_no_fail(result) + + def test_cli_list_failed(self): + mock_item = self.set_mock('SoftLayer_Network_LBaaS_LoadBalancer', + 'getAllObjects') + mock_item.return_value = None + result = self.run_command(['loadbal', 'list']) + self.assert_no_fail(result) + + def test_pool(self): + result = self.run_command(['loadbal', 'pool-add', '1111111', '-f 1000', '-b 220', '-c 100']) + self.assert_no_fail(result) + + def test_pool_sticky(self): + result = self.run_command(['loadbal', 'pool-add', '1111111', '-f 1000', '-b 220', '-s']) + self.assert_no_fail(result) + + def test_pool_1(self): + result = self.run_command(['loadbal', 'pool-add', '1111111', '-f 1000', '-b 220']) + self.assert_no_fail(result) + + def test_pool_uuid(self): + result = self.run_command(['loadbal', 'pool-add', '13d08cd1-5533-47b4-b71c-4b6b9dc10000', + '-f 910', '-b 210', '-c 100']) + self.assert_no_fail(result) + + def test_delete_pool(self): + result = self.run_command(['loadbal', 'pool-del', '111111', 'b3a3fdf7-8c16-4e87-aa73-decff510000']) + self.assert_no_fail(result) + + def test_edit_pool(self): + result = self.run_command(['loadbal', 'pool-edit', '111111', '370a9f12-b3be-47b3-bfa5-8e460010000', '-f 510', + '-b 256', '-c 5']) + self.assert_no_fail(result) + + def test_add_7p(self): + result = self.run_command(['loadbal', 'l7pool-add', '0a2da082-4474-4e16-9f02-4de959210000', '-n test', + '-S 10.175.106.180:265:20', '-s']) + self.assert_no_fail(result) + + def test_add_7p_server(self): + result = self.run_command(['loadbal', 'l7pool-add', '111111', + '-S 10.175.106.180:265:20', '-n test', '-s']) + self.assert_no_fail(result) + + def test_del_7p(self): + result = self.run_command(['loadbal', 'l7pool-del', '123456']) + self.assert_no_fail(result) + + def test_add_7p_server_fail(self): + result = self.run_command(['loadbal', 'l7pool-add', '123456', + '-S 10.175.106.180:265:20:20', '-n test', '-s']) + self.assertIsInstance(result.exception, ArgumentError) + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_listener') + def test_pool_fail(self, add_lb_pool): + add_lb_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command(['loadbal', 'pool-add', '123456', '-f 1000', '-b 220', '-c 100']) + self.assert_no_fail(result) + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_listener') + def test_pool_sticky_fail(self, add_lb_pool): + add_lb_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command(['loadbal', 'pool-add', '123456', '-f 1000', '-b 220', '-s']) + self.assert_no_fail(result) + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_listener') + def test_pool_1_fail(self, add_lb_pool): + add_lb_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command(['loadbal', 'pool-add', '123456', '-f 1000', '-b 220']) + self.assert_no_fail(result) + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_listener') + def test_pool_uuid_fail(self, add_lb_pool): + add_lb_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command( + ['loadbal', 'pool-add', '13d08cd1-5533-47b4-b71c-4b6b9dc10000', '-f 910', '-b 210', '-c 100']) + self.assert_no_fail(result) + + @mock.patch('SoftLayer.LoadBalancerManager.remove_lb_listener') + def test_delete_pool_fail(self, del_lb_pool): + del_lb_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command(['loadbal', 'pool-del', '123456', 'b3a3fdf7-8c16-4e87-aa73-decff510000']) + self.assert_no_fail(result) + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_listener') + def test_edit_pool_fail(self, edit_lb_pool): + edit_lb_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command(['loadbal', 'pool-edit', '815248', '370a9f12-b3be-47b3-bfa5-8e10000c013f', '-f 510', + '-b 256', '-c 5']) + self.assert_no_fail(result) + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_l7_pool') + def test_add_7p_fail(self, add_lb_17_pool): + add_lb_17_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command(['loadbal', 'l7pool-add', '0a2da082-4474-4e16-9f02-4de10009b85', '-n test', + '-S 10.175.106.180:265:20', '-s']) + self.assert_no_fail(result) + + @mock.patch('SoftLayer.LoadBalancerManager.del_lb_l7_pool') + def test_del_7p_fail(self, del_lb_17_pool): + del_lb_17_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) + result = self.run_command(['loadbal', 'l7pool-del', '123456']) + self.assert_no_fail(result) From 171d15acbfe6a1d606cdd8cf91ab55b590a02c81 Mon Sep 17 00:00:00 2001 From: Daniel Cabero Barrios Date: Mon, 26 Aug 2019 09:32:12 -0400 Subject: [PATCH 14/23] Fix error H306 --- tests/CLI/modules/loadbal_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CLI/modules/loadbal_tests.py b/tests/CLI/modules/loadbal_tests.py index 26505fcc8..2e78289c8 100644 --- a/tests/CLI/modules/loadbal_tests.py +++ b/tests/CLI/modules/loadbal_tests.py @@ -7,8 +7,8 @@ from mock import mock import SoftLayer -from SoftLayer import testing from SoftLayer.CLI.exceptions import ArgumentError +from SoftLayer import testing class LoadBalancerTests(testing.TestCase): From 439b07e890846a285d358af8310226001fdcee72 Mon Sep 17 00:00:00 2001 From: Daniel Cabero Barrios Date: Mon, 26 Aug 2019 10:28:46 -0400 Subject: [PATCH 15/23] add fixture load balancer listener and L7pool --- .../SoftLayer_Network_LBaaS_L7Pool.py | 44 ++++++++++++++++++- .../SoftLayer_Network_LBaaS_Listener.py | 44 ++++++++++++++++++- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py index 2d66fcd5c..0acbc6ae9 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_L7Pool.py @@ -1,2 +1,42 @@ -createL7Pool = {} -deleteObject = {} +createL7Pool = {'accountId': 1234, + 'address': '01-307608-ams01.clb.appdomain.cloud', + 'createDate': '2019-08-12T07:49:43-06:00', + 'id': 1111111, + 'isPublic': 0, + 'locationId': 265592, + 'modifyDate': '2019-08-13T16:26:06-06:00', + 'name': 'dcabero-01', + 'operatingStatus': 'ONLINE', + 'provisioningStatus': 'ACTIVE', + 'type': 0, + 'useSystemPublicIpPool': 1, + 'uuid': '1a1aa111-4474-4e16-9f02-4de959229b85', + 'listenerCount': 4, + 'memberCount': 1, + 'datacenter': { + 'id': 265592, + 'longName': 'Amsterdam 1', + 'name': 'ams01', + 'statusId': 2 + }} +deleteObject = {'accountId': 1234, + 'address': '01-307608-ams01.clb.appdomain.cloud', + 'createDate': '2019-08-12T07:49:43-06:00', + 'id': 1111111, + 'isPublic': 0, + 'locationId': 265592, + 'modifyDate': '2019-08-13T16:26:06-06:00', + 'name': 'dcabero-01', + 'operatingStatus': 'ONLINE', + 'provisioningStatus': 'ACTIVE', + 'type': 0, + 'useSystemPublicIpPool': 1, + 'uuid': '1a1aa111-4474-4e16-9f02-4de959229b85', + 'listenerCount': 4, + 'memberCount': 1, + 'datacenter': { + 'id': 265592, + 'longName': 'Amsterdam 1', + 'name': 'ams01', + 'statusId': 2 + }} diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py index 5af3844e1..57a2459e8 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_Listener.py @@ -1,3 +1,43 @@ # https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_Listener/ -updateLoadBalancerProtocols = {} -deleteLoadBalancerProtocols = {} +updateLoadBalancerProtocols = {'accountId': 1234, + 'address': '01-307608-ams01.clb.appdomain.cloud', + 'createDate': '2019-08-12T07:49:43-06:00', + 'id': 1111111, + 'isPublic': 0, + 'locationId': 265592, + 'modifyDate': '2019-08-13T16:26:06-06:00', + 'name': 'dcabero-01', + 'operatingStatus': 'ONLINE', + 'provisioningStatus': 'ACTIVE', + 'type': 0, + 'useSystemPublicIpPool': 1, + 'uuid': '1a1aa111-4474-4e16-9f02-4de959229b85', + 'listenerCount': 4, + 'memberCount': 1, + 'datacenter': { + 'id': 265592, + 'longName': 'Amsterdam 1', + 'name': 'ams01', + 'statusId': 2 + }} +deleteLoadBalancerProtocols = {'accountId': 1234, + 'address': '01-307608-ams01.clb.appdomain.cloud', + 'createDate': '2019-08-12T07:49:43-06:00', + 'id': 1111111, + 'isPublic': 0, + 'locationId': 265592, + 'modifyDate': '2019-08-13T16:26:06-06:00', + 'name': 'dcabero-01', + 'operatingStatus': 'ONLINE', + 'provisioningStatus': 'ACTIVE', + 'type': 0, + 'useSystemPublicIpPool': 1, + 'uuid': '1a1aa111-4474-4e16-9f02-4de959229b85', + 'listenerCount': 4, + 'memberCount': 1, + 'datacenter': { + 'id': 265592, + 'longName': 'Amsterdam 1', + 'name': 'ams01', + 'statusId': 2 + }} From 8d48042f3b40009956193a331b2d5c562fad0d86 Mon Sep 17 00:00:00 2001 From: ATGE Date: Mon, 26 Aug 2019 11:31:09 -0400 Subject: [PATCH 16/23] added try-except blocks --- SoftLayer/CLI/loadbal/health.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/SoftLayer/CLI/loadbal/health.py b/SoftLayer/CLI/loadbal/health.py index 19826ea98..bc0aac629 100644 --- a/SoftLayer/CLI/loadbal/health.py +++ b/SoftLayer/CLI/loadbal/health.py @@ -4,6 +4,7 @@ import SoftLayer from SoftLayer.CLI import environment from SoftLayer.CLI import exceptions +from SoftLayer.exceptions import SoftLayerAPIError from SoftLayer import utils @@ -55,9 +56,9 @@ def cli(env, identifier, uuid, interval, retry, timeout, url): for key in clean_template.keys(): check[key] = clean_template[key] - result = mgr.update_lb_health_monitors(lb_uuid, [check]) - - if result: + try: + mgr.update_lb_health_monitors(lb_uuid, [check]) click.secho('Health Check {} updated successfully'.format(uuid), fg='green') - else: - click.secho('ERROR: Failed to update {}'.format(uuid), fg='red') + except SoftLayerAPIError as exception: + click.secho('Failed to update {}'.format(uuid), fg='red') + click.secho("ERROR: {}".format(exception.faultString), fg='red') From 3db7f93d9a57f6a4e27e16ca1a93f8da180ae742 Mon Sep 17 00:00:00 2001 From: ATGE Date: Mon, 26 Aug 2019 11:34:44 -0400 Subject: [PATCH 17/23] added required datatypes --- .../SoftLayer_Network_LBaaS_LoadBalancer.py | 138 +++++++++++++++--- 1 file changed, 115 insertions(+), 23 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py index d9dcce0ca..12668f5cd 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py @@ -1,29 +1,121 @@ getObject = { - 'accountId': 1234, - 'address': '01-307608-ams01.clb.appdomain.cloud', - 'createDate': '2019-08-12T07:49:43-06:00', - 'id': 1111111, - 'isPublic': 0, - 'locationId': 265592, - 'modifyDate': '2019-08-13T16:26:06-06:00', - 'name': 'dcabero-01', - 'operatingStatus': 'ONLINE', - 'provisioningStatus': 'ACTIVE', - 'type': 0, - 'useSystemPublicIpPool': 1, - 'uuid': '1a1aa111-4474-4e16-9f02-4de959229b85', - 'listenerCount': 4, - 'memberCount': 1, - 'datacenter': { - 'id': 265592, - 'longName': 'Amsterdam 1', - 'name': 'ams01', - 'statusId': 2 + 'accountId': 1234, + 'address': '01-307608-ams01.clb.appdomain.cloud', + 'createDate': '2019-08-12T07:49:43-06:00', + 'id': 1111111, + 'isPublic': 0, + 'locationId': 265592, + 'modifyDate': '2019-08-13T16:26:06-06:00', + 'name': 'dcabero-01', + 'operatingStatus': 'ONLINE', + 'provisioningStatus': 'ACTIVE', + 'type': 0, + 'useSystemPublicIpPool': 1, + 'uuid': '1a1aa111-4474-4e16-9f02-4de959229b85', + 'listenerCount': 4, + 'memberCount': 1, + 'previousErrorText': 'test', + 'datacenter': { + 'id': 265592, + 'longName': 'Amsterdam 1', + 'name': 'ams01', + 'statusId': 2 + }, + 'healthMonitors': [ + { + 'createDate': '2019-08-20T18:05:09-04:00', + 'interval': 5, + 'maxRetries': 2, + 'modifyDate': '2019-08-20T18:05:18-04:00', + 'monitorType': 'HTTP', + 'provisioningStatus': 'ACTIVE', + 'timeout': 2, + 'urlPath': '/', + 'uuid': 'c11111c1-f5ab-4c15-ba96-d7b95dc7c824' } - } + ], + 'l7Pools': [ + { + 'createDate': '2019-08-19T16:33:37-04:00', + 'id': 222222, + 'loadBalancingAlgorithm': 'ROUNDROBIN', + 'modifyDate': None, + 'name': 'test', + 'protocol': 'HTTP', + 'provisioningStatus': 'ACTIVE', + 'uuid': 'a1111111-c5e7-413f-9f78-84f6c5e1ca04' + } + ], + 'listeners': [ + { + 'defaultPool': { + 'healthMonitor': { + 'uuid': '222222ab-bbcc-4f32-9b31-1b6d3a1959c8' + }, + 'protocol': 'HTTP', + 'protocolPort': 256, + 'uuid': 'ab1a1abc-0e83-4690-b5d4-1359625dba8f', + } + }, + {'connectionLimit': None, + 'createDate': '2019-08-21T17:19:25-04:00', + 'defaultPool': {'createDate': '2019-08-21T17:19:25-04:00', + 'healthMonitor': {'createDate': '2019-08-21T17:17:04-04:00', + 'id': 859330, + 'interval': 5, + 'maxRetries': 2, + 'modifyDate': '2019-08-21T17:17:15-04:00', + 'monitorType': 'HTTP', + 'provisioningStatus': 'ACTIVE', + 'timeout': 2, + 'urlPath': '/', + 'uuid': '55e00152-75fd-4f94-9263-cb4c6e005f12'}, + 'loadBalancingAlgorithm': 'ROUNDROBIN', + 'members': [{'address': '10.136.4.220', + 'createDate': '2019-08-12T09:49:43-04:00', + 'id': 1023118, + 'modifyDate': '2019-08-12T09:52:54-04:00', + 'provisioningStatus': 'ACTIVE', + 'uuid': 'ba23a166-faa4-4eb2-96e7-ef049d65ce60', + 'weight': 50}], + 'modifyDate': '2019-08-21T17:19:33-04:00', + 'protocol': 'HTTP', + 'protocolPort': 230, + 'provisioningStatus': 'ACTIVE', + 'uuid': '1c5f3ba6-ec7d-4cf8-8815-9bb174224a76'}, + 'id': 889072, + 'l7Policies': [{'action': 'REJECT', + 'createDate': '2019-08-21T18:17:41-04:00', + 'id': 215204, + 'modifyDate': None, + 'name': 'trestst', + 'priority': 1, + 'redirectL7PoolId': None, + 'uuid': 'b8c30aae-3979-49a7-be8c-fb70e43a6b4b'}], + 'modifyDate': '2019-08-22T10:58:02-04:00', + 'protocol': 'HTTP', + 'protocolPort': 110, + 'provisioningStatus': 'ACTIVE', + 'tlsCertificateId': None, + 'uuid': 'a509723d-a3cb-4ae4-bc5b-5ecf04f890ff'} + ], + 'members': [ + { + 'address': '10.0.0.1', + 'createDate': '2019-08-12T09:49:43-04:00', + 'modifyDate': '2019-08-12T09:52:54-04:00', + 'provisioningStatus': 'ACTIVE', + 'uuid': 'ba23a166-faa4-4eb2-96e7-ef049d65ce60', + 'weight': 50 + } + ], + 'sslCiphers': [ + { + 'id': 2, 'name': 'ECDHE-RSA-AES256-GCM-SHA384' + } + ], +} getAllObjects = [getObject] - - getLoadBalancerMemberHealth = [ { 'poolUuid': '1c5f3ba6-ec7d-4cf8-8815-9bb174224a76', From 96753cd7af207a0d2a6fa9aed69b9f610fdfbd63 Mon Sep 17 00:00:00 2001 From: ATGE Date: Mon, 26 Aug 2019 11:36:34 -0400 Subject: [PATCH 18/23] added health, detail, members test --- tests/CLI/modules/loadbal_tests.py | 109 +++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 tests/CLI/modules/loadbal_tests.py diff --git a/tests/CLI/modules/loadbal_tests.py b/tests/CLI/modules/loadbal_tests.py new file mode 100644 index 000000000..549b28387 --- /dev/null +++ b/tests/CLI/modules/loadbal_tests.py @@ -0,0 +1,109 @@ +""" + SoftLayer.tests.CLI.modules.loadbal + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + :license: MIT, see LICENSE for more details. +""" + +import mock + +from SoftLayer.CLI.exceptions import ArgumentError +from SoftLayer import exceptions +from SoftLayer.fixtures import SoftLayer_Network_LBaaS_LoadBalancer +from SoftLayer import testing + + +class LoadBalTests(testing.TestCase): + + @mock.patch('SoftLayer.CLI.loadbal.members.click') + def test_lb_member_add_private(self, click): + lbaas_id = '1111111' + member_ip_address = '10.0.0.1' + result = self.run_command(['loadbal', 'member-add', '--private', '-m', member_ip_address, lbaas_id]) + output = 'Member {} added'.format(member_ip_address) + self.assert_no_fail(result) + click.secho.assert_called_with(output, fg='green') + + @mock.patch('SoftLayer.CLI.loadbal.members.click') + def test_lb_member_add_public(self, click): + lbaas_id = '1111111' + member_ip_address = '10.0.0.1' + result = self.run_command(['loadbal', 'member-add', '--public', '-m', member_ip_address, lbaas_id]) + output = 'Member {} added'.format(member_ip_address) + self.assert_no_fail(result) + click.secho.assert_called_with(output, fg='green') + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_member') + def test_lb_member_add_public_fails(self, add_lb_member): + lbaas_id = '1111111' + member_ip_address = '10.0.0.1' + fault_string = 'publicIpAddress must be a string' + add_lb_member.side_effect = exceptions.SoftLayerAPIError(mock.ANY, fault_string) + result = self.run_command(['loadbal', 'member-add', '--public', '-m', member_ip_address, lbaas_id]) + self.assertIn('This LB requires a Public IP address for its members and none was supplied', + result.output) + self.assertIn("ERROR: {}".format(fault_string), + result.output) + + @mock.patch('SoftLayer.LoadBalancerManager.add_lb_member') + def test_lb_member_add_private_fails(self, add_lb_member): + lbaas_id = '1111111' + member_ip_address = '10.0.0.1' + fault_string = 'privateIpAddress must be a string' + add_lb_member.side_effect = exceptions.SoftLayerAPIError(mock.ANY, fault_string) + result = self.run_command(['loadbal', 'member-add', '--private', '-m', member_ip_address, lbaas_id]) + self.assertIn('This LB requires a Private IP address for its members and none was supplied', + result.output) + self.assertIn("ERROR: {}".format(fault_string), + result.output) + + @mock.patch('SoftLayer.managers.load_balancer.LoadBalancerManager.delete_lb_member') + def test_lb_member_del_fails(self, delete): + lbaas_id = '1111111' + lbaas_member_uuid = "x123x123-123x-123x-123x-123a123b123c" + delete.side_effect = exceptions.SoftLayerAPIError(mock.ANY, mock.ANY) + result = self.run_command(['loadbal', 'member-del', '-m', lbaas_member_uuid, lbaas_id]) + self.assertIn("ERROR:", result.output) + + @mock.patch('SoftLayer.CLI.loadbal.members.click') + def test_lb_member_del(self, click): + lbaas_id = '1111111' + lbaas_member_uuid = "x123x123-123x-123x-123x-123a123b123c" + result = self.run_command(['loadbal', 'member-del', '-m', lbaas_member_uuid, lbaas_id]) + output = 'Member {} removed'.format(lbaas_member_uuid) + self.assert_no_fail(result) + click.secho.assert_called_with(output, fg='green') + + @mock.patch('SoftLayer.CLI.loadbal.health.click') + def test_lb_health_manage(self, click): + lb_id = '1111111' + lb_check_uuid = '222222ab-bbcc-4f32-9b31-1b6d3a1959c8' + result = self.run_command(['loadbal', 'health', lb_id, '--uuid', lb_check_uuid, + '-i', '60', '-r', '10', '-t', '10', '-u', '/']) + self.assert_no_fail(result) + output = 'Health Check {} updated successfully'.format(lb_check_uuid) + click.secho.assert_called_with(output, fg='green') + + def test_lb_health_manage_args_time_fails(self): + result = self.run_command(['lb', 'health', '1111111', '--uuid', '222222ab-bbcc-4f32-9b31-1b6d3a1959c8']) + self.assertIsInstance(result.exception, ArgumentError) + + @mock.patch('SoftLayer.LoadBalancerManager.get_lb') + def test_lb_health_update_tcp_url_fails(self, get_lb): + get_lb.return_value = SoftLayer_Network_LBaaS_LoadBalancer.getObject + get_lb.return_value['listeners'][0]['defaultPool']['protocol'] = 'TCP' + + result = self.run_command(['lb', 'health', '1111111', '--uuid', '222222ab-bbcc-4f32-9b31-1b6d3a1959c8', + '-i', '60', '-r', '10', '-t', '10', '-u', '/']) + self.assertIsInstance(result.exception, ArgumentError) + + @mock.patch('SoftLayer.LoadBalancerManager.update_lb_health_monitors') + def test_lb_health_update_fails(self, update_lb_health_monitors): + update_lb_health_monitors.side_effect = exceptions.SoftLayerAPIError(mock.ANY, mock.ANY) + + result = self.run_command(['lb', 'health', '1111111', '--uuid', '222222ab-bbcc-4f32-9b31-1b6d3a1959c8', + '-i', '60', '-r', '10', '-t', '10', '-u', '/']) + self.assertIn("ERROR:", result.output) + + def test_lb_detail(self): + result = self.run_command(['lb', 'detail', '1111111']) + self.assert_no_fail(result) From 584a142e129316ea0a2e25481eea8850d14fe424 Mon Sep 17 00:00:00 2001 From: Christopher Gallo Date: Mon, 26 Aug 2019 16:24:25 -0500 Subject: [PATCH 19/23] fixed merge conflict error. accidentally removed a line in merge conflict. --- tests/CLI/modules/loadbal_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/CLI/modules/loadbal_tests.py b/tests/CLI/modules/loadbal_tests.py index 7676950ba..48e4e77f1 100644 --- a/tests/CLI/modules/loadbal_tests.py +++ b/tests/CLI/modules/loadbal_tests.py @@ -119,6 +119,7 @@ def test_add_7p_fail(self, add_lb_17_pool): def test_del_7p_fail(self, del_lb_17_pool): del_lb_17_pool.side_effect = SoftLayer.exceptions.SoftLayerAPIError(mock.ANY, mock) result = self.run_command(['loadbal', 'l7pool-del', '123456']) + self.assert_no_fail(result) @mock.patch('SoftLayer.CLI.loadbal.members.click') def test_lb_member_add_private(self, click): From 6df37877877ae75c21a75aef4d881e9aba935bdd Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Wed, 28 Aug 2019 12:58:17 -0400 Subject: [PATCH 20/23] Unit test for loadbal order, ns-list, ns-detail. --- SoftLayer/fixtures/SoftLayer_Account.py | 28 +++- ...Network_Application_Delivery_Controller.py | 19 +++ .../SoftLayer_Network_LBaaS_LoadBalancer.py | 20 +++ .../fixtures/SoftLayer_Product_Package.py | 123 ++++++++++++++++++ tests/CLI/modules/loadbal_tests.py | 79 +++++++++++ tests/managers/network_tests.py | 2 +- 6 files changed, 268 insertions(+), 3 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Account.py b/SoftLayer/fixtures/SoftLayer_Account.py index 1c8800628..7ef79715d 100644 --- a/SoftLayer/fixtures/SoftLayer_Account.py +++ b/SoftLayer/fixtures/SoftLayer_Account.py @@ -323,8 +323,32 @@ 'subnetType': 'PRIMARY', 'ipAddressCount': 10, 'virtualGuests': [], - 'hardware': [] - }] + 'hardware': [], + "podName": "dal05.pod04", + "networkVlan": { + "accountId": 123, + "id": 2581232, + "modifyDate": "2019-07-17T01:09:51+08:00", + "vlanNumber": 795 + } + }, + { + "gateway": "5.111.11.111", + "id": '111', + "modifyDate": "2018-07-24T17:14:57+08:00", + 'networkIdentifier': '10.0.0.1', + 'ipAddressCount': 10, + 'cidr': '/24', + 'virtualGuests': [], + 'hardware': [], + "networkVlanId": 22222, + "sortOrder": "2", + "subnetType": "SECONDARY_ON_VLAN", + "totalIpAddresses": "8", + "usableIpAddressCount": "5", + "version": 4 + } +] getSshKeys = [{'id': '100', 'label': 'Test 1'}, {'id': '101', 'label': 'Test 2', diff --git a/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py index 532968d50..4ba9b7328 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py +++ b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py @@ -17,6 +17,25 @@ 'password': 'aaaaa', 'username': 'root' }, + "primaryIpAddress": "159.122.22.222", + "subnets": [ + { + "broadcastAddress": "", + "cidr": 32, + "gateway": "", + "id": 74222, + "modifyDate": "2016-10-26T23:39:12+08:00", + "netmask": "255.255.255.255", + "networkIdentifier": "159.253.111.111", + "networkVlanId": 3611111, + "sortOrder": "4", + "subnetType": "STATIC_IP_ROUTED", + "totalIpAddresses": "2", + "usableIpAddressCount": "2", + "version": 4, + "addressSpace": "PUBLIC" + } + ], 'type': { 'keyName': 'NETSCALER_VPX', 'name': 'NetScaler VPX' diff --git a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py index 12668f5cd..1047a7ce8 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py +++ b/SoftLayer/fixtures/SoftLayer_Network_LBaaS_LoadBalancer.py @@ -116,6 +116,26 @@ ], } getAllObjects = [getObject] + +getLoadBalancer = { + "accountId": 3071234, + "createDate": "2019-08-12T21:49:43+08:00", + "id": 81234, + "isPublic": 0, + "locationId": 265592, + "modifyDate": "2019-08-14T06:26:06+08:00", + "name": "dcabero-01", + "uuid": "0a2da082-4474-4e16-9f02-4de11111", + "datacenter": { + "id": 265592, + "longName": "Amsterdam 1", + "name": "ams01", + "statusId": 2 + } +} + +cancelLoadBalancer = True + getLoadBalancerMemberHealth = [ { 'poolUuid': '1c5f3ba6-ec7d-4cf8-8815-9bb174224a76', diff --git a/SoftLayer/fixtures/SoftLayer_Product_Package.py b/SoftLayer/fixtures/SoftLayer_Product_Package.py index 186674282..b131f8916 100644 --- a/SoftLayer/fixtures/SoftLayer_Product_Package.py +++ b/SoftLayer/fixtures/SoftLayer_Product_Package.py @@ -784,6 +784,44 @@ 'sortOrder': 10}], 'subDescription': 'Bare Metal Server', 'unitSize': 1, + "itemPrices": [ + { + "hourlyRecurringFee": ".027", + "id": 205911, + "laborFee": "0", + "locationGroupId": 505, + "item": { + "capacity": "0", + "description": "Load Balancer Uptime", + "id": 10785, + "keyName": "LOAD_BALANCER_UPTIME", + } + }, + { + "hourlyRecurringFee": "0", + "id": 199467, + "laborFee": "0", + "locationGroupId": '', + "recurringFee": "0", + "item": { + "capacity": "0", + "description": "Load Balancer Bandwidth", + "id": 10051, + "keyName": "LOAD_BALANCER_BANDWIDTH", + } + }, + { + "hourlyRecurringFee": ".028", + "id": 205913, + "laborFee": "0", + "locationGroupId": 507, + "item": { + "capacity": "0", + "description": "Load Balancer Uptime", + "id": 10785, + "keyName": "LOAD_BALANCER_UPTIME", + } + }] }] getItems = [ @@ -1144,6 +1182,91 @@ 'quantity': 1 } +itemsLoadbal = [ + { + "capacity": "0", + "description": "Load Balancer as a Service", + "id": 10043, + "keyName": "LOAD_BALANCER_AS_A_SERVICE", + "itemCategory": { + "categoryCode": "load_balancer_as_a_service", + "id": 1116, + "name": "Load Balancer As A Service", + }, + "prices": [ + { + "hourlyRecurringFee": "0", + "id": 199447, + "locationGroupId": '', + "recurringFee": "0", + } + ] + }, + { + "capacity": "0", + "description": "Load Balancer Uptime", + "id": 10785, + "keyName": "LOAD_BALANCER_UPTIME", + "itemCategory": { + "categoryCode": "load_balancer_uptime", + "id": 1119, + "name": "Load Balancer Uptime", + }, + "prices": [ + { + "hourlyRecurringFee": ".028", + "id": 205913, + "locationGroupId": 507, + }]} +] + +regionsLoadbal = [{'description': 'WDC01 - Washington, DC - East Coast U.S.', + 'keyname': 'WASHINGTON_DC', + 'location': {'location': {'id': 37473, + 'longName': 'Washington 1', + 'name': 'wdc01', + "groups": [ + { + "description": "Location Group 4", + "id": 507, + "locationGroupTypeId": 82, + "name": "Location Group 4", + "locationGroupType": { + "name": "PRICING" + } + }, + { + "description": "COS Cross Region - EU", + "id": 1303, + "locationGroupTypeId": 82, + "name": "eu", + "locationGroupType": { + "name": "PRICING" + } + }, + { + "description": "COS Regional Frankfurt", + "id": 1783, + "locationGroupTypeId": 82, + "name": "eu-de", + "locationGroupType": { + "name": "PRICING" + } + } + ] + }}, + 'sortOrder': 10}] + +getAllObjectsLoadbal = [ + { + "id": 805, + "keyName": "LBAAS", + "name": "Load Balancer As A Service (LBaaS)", + "items": itemsLoadbal, + "regions": regionsLoadbal + } +] + getAllObjectsDH = [{ "subDescription": "Dedicated Host", "name": "Dedicated Host", diff --git a/tests/CLI/modules/loadbal_tests.py b/tests/CLI/modules/loadbal_tests.py index 48e4e77f1..99549aa79 100644 --- a/tests/CLI/modules/loadbal_tests.py +++ b/tests/CLI/modules/loadbal_tests.py @@ -8,6 +8,7 @@ import SoftLayer from SoftLayer.CLI.exceptions import ArgumentError from SoftLayer import exceptions +from SoftLayer.fixtures import SoftLayer_Product_Package from SoftLayer.fixtures import SoftLayer_Network_LBaaS_LoadBalancer from SoftLayer import testing @@ -214,3 +215,81 @@ def test_lb_health_update_fails(self, update_lb_health_monitors): def test_lb_detail(self): result = self.run_command(['lb', 'detail', '1111111']) self.assert_no_fail(result) + + def test_order(self): + result = self.run_command(['loadbal', 'order', '--name', 'test', '--datacenter', 'par01', '--label', + 'labeltest', '--subnet', '759282']) + + self.assert_no_fail(result) + + def test_order_with_frontend(self): + result = self.run_command(['loadbal', 'order', '--name', 'test', '--datacenter', 'par01', '--label', + 'labeltest', '--frontend', 'TCP:80', '--backend', 'TCP:80', '--subnet', '759282']) + + self.assert_no_fail(result) + + def test_order_with_backend(self): + result = self.run_command(['loadbal', 'order', '--name', 'test', '--datacenter', 'par01', '--label', + 'labeltest', '--backend', 'HTTP:80', '--subnet', '759282']) + + self.assert_no_fail(result) + + def test_order_backend_fail(self): + result = self.run_command(['loadbal', 'order', '--name', 'test', '--datacenter', 'par01', '--label', + 'labeltest', '--backend', 'HTTP', '--subnet', '759282']) + + self.assertEqual(result.exit_code, 2) + self.assertIsInstance(result.exception, ArgumentError) + + def test_verify_order(self): + result = self.run_command(['loadbal', 'order', '--verify', '--name', 'test', '--datacenter', 'par01', '--label', + 'labeltest', '--subnet', '759282']) + + self.assert_no_fail(result) + + def test_order_options(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = SoftLayer_Product_Package.getAllObjectsLoadbal + result = self.run_command(['loadbal', 'order-options']) + + self.assert_no_fail(result) + + def test_order_options_with_datacenter(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = SoftLayer_Product_Package.getAllObjectsLoadbal + result = self.run_command(['loadbal', 'order-options', '--datacenter', 'ams03']) + + self.assert_no_fail(result) + + def test_cancel(self): + result = self.run_command(['loadbal', 'cancel', '11111']) + + self.assert_no_fail(result) + self.assert_called_with('SoftLayer_Network_LBaaS_LoadBalancer', 'cancelLoadBalancer') + + @mock.patch('SoftLayer.LoadBalancerManager.cancel_lbaas') + def test_cancel_fail(self, cancel_lbaas): + fault_string = 'Id must be string' + cancel_lbaas.side_effect = exceptions.SoftLayerAPIError(mock.ANY, fault_string) + result = self.run_command(['loadbal', 'cancel', '11111']) + + self.assertIn("ERROR: {}".format(fault_string), + result.output) + + def test_ns_list(self): + result = self.run_command(['loadbal', 'ns-list']) + + self.assert_no_fail(result) + + def test_ns_list_empty(self): + mock = self.set_mock('SoftLayer_Account', 'getApplicationDeliveryControllers') + mock.return_value = [] + + result = self.run_command(['loadbal', 'ns-list']) + + self.assert_no_fail(result) + + def test_ns_detail(self): + result = self.run_command(['loadbal', 'ns-detail', '11111']) + + self.assert_no_fail(result) diff --git a/tests/managers/network_tests.py b/tests/managers/network_tests.py index a87441a99..fd986e2ea 100644 --- a/tests/managers/network_tests.py +++ b/tests/managers/network_tests.py @@ -435,7 +435,7 @@ def test_resolve_global_ip_ids_no_results(self): def test_resolve_subnet_ids(self): _id = self.network.resolve_subnet_ids('10.0.0.1/29') - self.assertEqual(_id, ['100']) + self.assertEqual(_id, ['100', '111']) def test_resolve_subnet_ids_no_results(self): mock = self.set_mock('SoftLayer_Account', 'getSubnets') From de382b3116066438fd8c8d1477718ebe953429d1 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Wed, 28 Aug 2019 13:27:24 -0400 Subject: [PATCH 21/23] Fix file analysis. --- tests/CLI/modules/loadbal_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CLI/modules/loadbal_tests.py b/tests/CLI/modules/loadbal_tests.py index 99549aa79..b87dab6e9 100644 --- a/tests/CLI/modules/loadbal_tests.py +++ b/tests/CLI/modules/loadbal_tests.py @@ -8,8 +8,8 @@ import SoftLayer from SoftLayer.CLI.exceptions import ArgumentError from SoftLayer import exceptions -from SoftLayer.fixtures import SoftLayer_Product_Package from SoftLayer.fixtures import SoftLayer_Network_LBaaS_LoadBalancer +from SoftLayer.fixtures import SoftLayer_Product_Package from SoftLayer import testing From 745ec85bca1ab7061cafde8488ed4bb18f9586ed Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Wed, 28 Aug 2019 15:12:34 -0400 Subject: [PATCH 22/23] Fix file analysis. --- ..._Network_Application_Delivery_Controller.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py index 4ba9b7328..5f29c915f 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py +++ b/SoftLayer/fixtures/SoftLayer_Network_Application_Delivery_Controller.py @@ -13,11 +13,27 @@ 'longName': 'Dallas 9', 'name': 'dal09', }, + "networkVlans": [ + { + "accountId": 11111, + "id": 33333, + "modifyDate": "2019-07-17T01:09:38+08:00", + "name": "FirewallTesting", + "primarySubnetId": 91111, + "vlanNumber": 1711 + }, + { + "accountId": 11111, + "id": 862222, + "modifyDate": "2019-07-17T01:09:42+08:00", + "primarySubnetId": 502211, + "vlanNumber": 722 + } + ], 'password': { 'password': 'aaaaa', 'username': 'root' }, - "primaryIpAddress": "159.122.22.222", "subnets": [ { "broadcastAddress": "", From 8448ccd729cf19649eaf918c66078b655f74c866 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 28 Aug 2019 14:23:04 -0500 Subject: [PATCH 23/23] #1158 added LB docs --- SoftLayer/managers/cdn.py | 10 ++--- SoftLayer/managers/load_balancer.py | 11 +++-- docs/cli/loadbal.rst | 62 +++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 docs/cli/loadbal.rst diff --git a/SoftLayer/managers/cdn.py b/SoftLayer/managers/cdn.py index 51dfb5252..95a32f870 100644 --- a/SoftLayer/managers/cdn.py +++ b/SoftLayer/managers/cdn.py @@ -74,11 +74,11 @@ def add_origin(self, unique_id, origin, path, origin_type="server", header=None, :param str protocol: the protocol of the origin (default: HTTP) :param str bucket_name: name of the available resource :param str file_extensions: file extensions that can be stored in the CDN, e.g. "jpg,png" - :param str optimize_for: performance configuration, available options: web, video, and file - where: - 'web' --> 'General web delivery' - 'video' --> 'Video on demand optimization' - 'file' --> 'Large file optimization' + :param str optimize_for: performance configuration, available options: web, video, and file where: + + - 'web' = 'General web delivery' + - 'video' = 'Video on demand optimization' + - 'file' = 'Large file optimization' :param str cache_query: rules with the following formats: 'include-all', 'ignore-all', 'include: space separated query-names', 'ignore: space separated query-names'.' diff --git a/SoftLayer/managers/load_balancer.py b/SoftLayer/managers/load_balancer.py index 072077ef0..ea67e469c 100644 --- a/SoftLayer/managers/load_balancer.py +++ b/SoftLayer/managers/load_balancer.py @@ -76,8 +76,11 @@ def get_lb(self, identifier, mask=None): def update_lb_health_monitors(self, uuid, checks): """calls SoftLayer_Network_LBaaS_HealthMonitor::updateLoadBalancerHealthMonitors() - https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_HealthMonitor/updateLoadBalancerHealthMonitors/ - https://sldn.softlayer.com/reference/datatypes/SoftLayer_Network_LBaaS_LoadBalancerHealthMonitorConfiguration/ + - `updateLoadBalancerHealthMonitors `_ + - `SoftLayer_Network_LBaaS_LoadBalancerHealthMonitorConfiguration `_ + :param uuid: loadBalancerUuid :param checks list: SoftLayer_Network_LBaaS_LoadBalancerHealthMonitorConfiguration[] """ @@ -137,8 +140,8 @@ def add_lb_listener(self, identifier, listener): def add_lb_l7_pool(self, identifier, pool, members, health, session): """Creates a new l7 pool for a LBaaS instance - https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_L7Pool/createL7Pool/ - https://cloud.ibm.com/docs/infrastructure/loadbalancer-service?topic=loadbalancer-service-api-reference + - https://sldn.softlayer.com/reference/services/SoftLayer_Network_LBaaS_L7Pool/createL7Pool/ + - https://cloud.ibm.com/docs/infrastructure/loadbalancer-service?topic=loadbalancer-service-api-reference :param identifier: UUID of the LBaaS instance :param pool SoftLayer_Network_LBaaS_L7Pool: Description of the pool diff --git a/docs/cli/loadbal.rst b/docs/cli/loadbal.rst new file mode 100644 index 000000000..b1a6a0dcc --- /dev/null +++ b/docs/cli/loadbal.rst @@ -0,0 +1,62 @@ +.. _cli_loadbalancer: + +LoadBalancers +=================================== +These commands were added in version `5.8.0 `_ + +LBaaS Commands +~~~~~~~~~~~~~~ + +- `LBaaS Product `_ +- `LBaaS Documentation `_ + +.. click:: SoftLayer.CLI.loadbal.detail:cli + :prog: loadbal detail + :show-nested: +.. click:: SoftLayer.CLI.loadbal.list:cli + :prog: loadbal list + :show-nested: +.. click:: SoftLayer.CLI.loadbal.health:cli + :prog: loadbal health + :show-nested: +.. click:: SoftLayer.CLI.loadbal.members:add + :prog: loadbal member-add + :show-nested: +.. click:: SoftLayer.CLI.loadbal.members:remove + :prog: loadbal member-remote + :show-nested: +.. click:: SoftLayer.CLI.loadbal.pools:add + :prog: loadbal pool-add + :show-nested: +.. click:: SoftLayer.CLI.loadbal.pools:edit + :prog: loadbal pool-edit + :show-nested: +.. click:: SoftLayer.CLI.loadbal.pools:delete + :prog: loadbal pool-delete + :show-nested: +.. click:: SoftLayer.CLI.loadbal.pools:l7pool_add + :prog: loadbal l7pool-add + :show-nested: +.. click:: SoftLayer.CLI.loadbal.pools:l7pool_del + :prog: loadbal l7pool-del + :show-nested: +.. click:: SoftLayer.CLI.loadbal.order:order + :prog: loadbal order + :show-nested: +.. click:: SoftLayer.CLI.loadbal.order:order_options + :prog: loadbal order-options + :show-nested: +.. click:: SoftLayer.CLI.loadbal.order:cancel + :prog: loadbal cancel + :show-nested: + + +NetScaler Commands +~~~~~~~~~~~~~~~~~~ + +.. click:: SoftLayer.CLI.loadbal.ns_detail:cli + :prog: loadbal ns-detail + :show-nested: +.. click:: SoftLayer.CLI.loadbal.ns_list:cli + :prog: loadbal ns-list + :show-nested: \ No newline at end of file