1"""Order and Cancel LBaaS instances.""" 2import click 3 4import SoftLayer 5from SoftLayer.CLI import environment 6from SoftLayer.CLI import exceptions 7from SoftLayer.CLI import formatting 8from SoftLayer.exceptions import SoftLayerAPIError 9from SoftLayer import utils 10 11 12# pylint: disable=unused-argument 13def parse_proto(ctx, param, value): 14 """Parses the frontend and backend cli options""" 15 proto = {'protocol': 'HTTP', 'port': 80} 16 splitout = value.split(':') 17 if len(splitout) != 2: 18 raise exceptions.ArgumentError("{}={} is not properly formatted.".format(param, value)) 19 proto['protocol'] = splitout[0] 20 proto['port'] = int(splitout[1]) 21 return proto 22 23 24@click.command() 25@click.option('--name', '-n', help='Label for this loadbalancer.', required=True) 26@click.option('--datacenter', '-d', help='Datacenter shortname (dal13).', required=True) 27@click.option('--label', '-l', help='A descriptive label for this loadbalancer.') 28@click.option('--frontend', '-f', required=True, default='HTTP:80', show_default=True, callback=parse_proto, 29 help='PROTOCOL:PORT string for incoming internet connections.') 30@click.option('--backend', '-b', required=True, default='HTTP:80', show_default=True, callback=parse_proto, 31 help='PROTOCOL:PORT string for connecting to backend servers.') 32@click.option('--method', '-m', help="Balancing Method.", default='ROUNDROBIN', show_default=True, 33 type=click.Choice(['ROUNDROBIN', 'LEASTCONNECTION', 'WEIGHTED_RR'])) 34@click.option('--subnet', '-s', required=True, 35 help="Private subnet Id to order the LB on. See `slcli lb order-options`") 36@click.option('--public', is_flag=True, default=False, show_default=True, help="Use a Public to Public loadbalancer.") 37@click.option('--verify', is_flag=True, default=False, show_default=True, 38 help="Only verify an order, dont actually create one.") 39@environment.pass_env 40def order(env, **args): 41 """Creates a LB. Protocols supported are TCP, HTTP, and HTTPS.""" 42 43 mgr = SoftLayer.LoadBalancerManager(env.client) 44 45 location = args.get('datacenter') 46 name = args.get('name') 47 description = args.get('label', None) 48 49 backend = args.get('backend') 50 frontend = args.get('frontend') 51 protocols = [ 52 { 53 "backendPort": backend.get('port'), 54 "backendProtocol": backend.get('protocol'), 55 "frontendPort": frontend.get('port'), 56 "frontendProtocol": frontend.get('protocol'), 57 "loadBalancingMethod": args.get('method'), 58 "maxConn": 1000 59 } 60 ] 61 62 # remove verify=True to place the order 63 receipt = mgr.order_lbaas(location, name, description, protocols, args.get('subnet'), 64 public=args.get('public'), verify=args.get('verify')) 65 table = parse_receipt(receipt) 66 env.fout(table) 67 68 69def parse_receipt(receipt): 70 """Takes an order receipt and nicely formats it for cli output""" 71 table = formatting.KeyValueTable(['Item', 'Cost'], title="Order: {}".format(receipt.get('orderId', 'Quote'))) 72 if receipt.get('prices'): 73 for price in receipt.get('prices'): 74 table.add_row([price['item']['description'], price['hourlyRecurringFee']]) 75 elif receipt.get('orderDetails'): 76 for price in receipt['orderDetails']['prices']: 77 table.add_row([price['item']['description'], price['hourlyRecurringFee']]) 78 79 return table 80 81 82@click.command() 83@click.option('--datacenter', '-d', help="Show only selected datacenter, use shortname (dal13) format.") 84@environment.pass_env 85def order_options(env, datacenter): 86 """Prints options for order a LBaaS""" 87 print("Prints options for ordering") 88 mgr = SoftLayer.LoadBalancerManager(env.client) 89 net_mgr = SoftLayer.NetworkManager(env.client) 90 package = mgr.lbaas_order_options() 91 92 if not datacenter: 93 data_table = formatting.KeyValueTable(['Datacenters', 'City']) 94 for region in package['regions']: 95 data_table.add_row([region['description'].split('-')[0], region['description'].split('-')[1]]) 96 # print(region) 97 env.fout(data_table) 98 click.secho("Use `slcli lb order-options --datacenter <DC>` " 99 "to find pricing information and private subnets for that specific site.") 100 101 else: 102 for region in package['regions']: 103 dc_name = utils.lookup(region, 'location', 'location', 'name') 104 105 # Skip locations if they are not the one requested. 106 if datacenter and dc_name != datacenter.lower(): 107 continue 108 109 l_groups = [] 110 for group in region['location']['location']['groups']: 111 l_groups.append(group.get('id')) 112 113 # Price lookups 114 prices = [] 115 price_table = formatting.KeyValueTable(['KeyName', 'Cost'], title='Prices') 116 for item in package['items']: 117 i_price = {'keyName': item['keyName']} 118 for price in item.get('prices', []): 119 if not price.get('locationGroupId'): 120 i_price['default_price'] = price.get('hourlyRecurringFee') 121 elif price.get('locationGroupId') in l_groups: 122 i_price['region_price'] = price.get('hourlyRecurringFee') 123 prices.append(i_price) 124 for price in prices: 125 if price.get('region_price'): 126 price_table.add_row([price.get('keyName'), price.get('region_price')]) 127 else: 128 price_table.add_row([price.get('keyName'), price.get('default_price')]) 129 130 # Vlan/Subnet Lookups 131 mask = "mask[networkVlan,podName,addressSpace]" 132 subnets = net_mgr.list_subnets(datacenter=dc_name, network_space='PRIVATE', mask=mask) 133 subnet_table = formatting.Table(['Id', 'Subnet', 'Vlan'], title='Private subnet') 134 135 for subnet in subnets: 136 # Only show these types, easier to filter here than in an API call. 137 if subnet.get('subnetType') != 'PRIMARY' and \ 138 subnet.get('subnetType') != 'ADDITIONAL_PRIMARY': 139 continue 140 space = "{}/{}".format(subnet.get('networkIdentifier'), subnet.get('cidr')) 141 vlan = "{}.{}".format(subnet['podName'], subnet['networkVlan']['vlanNumber']) 142 subnet_table.add_row([subnet.get('id'), space, vlan]) 143 144 env.fout(price_table) 145 env.fout(subnet_table) 146 147 148@click.command() 149@click.argument('identifier') 150@environment.pass_env 151def cancel(env, identifier): 152 """Cancels a LBaaS instance""" 153 154 mgr = SoftLayer.LoadBalancerManager(env.client) 155 uuid, _ = mgr.get_lbaas_uuid_id(identifier) 156 157 try: 158 mgr.cancel_lbaas(uuid) 159 click.secho("LB {} canceled succesfully.".format(identifier), fg='green') 160 except SoftLayerAPIError as exception: 161 click.secho("ERROR: {}".format(exception.faultString), fg='red') 162