Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
42ba6f5
#1026 groundwork for capacity commands
allmightyspiff Sep 17, 2018
cd3d417
#1026 functions for create-options
allmightyspiff Sep 19, 2018
475b1eb
got capacity create working
allmightyspiff Sep 20, 2018
a53a75a
Merge branch '1026' of github.com:allmightyspiff/softlayer-python int…
allmightyspiff Sep 21, 2018
af4fd92
list and detail support for capacity groups
allmightyspiff Sep 24, 2018
87b51a9
create-guest base files
allmightyspiff Sep 24, 2018
39f9e1b
support for creating guests, some more features for list and detail
allmightyspiff Sep 27, 2018
9f99ed3
#1026 mostly done with the bits that actually do things. still need u…
allmightyspiff Sep 28, 2018
fcd90dd
Merge branch 'master' of github.com:allmightyspiff/softlayer-python i…
allmightyspiff Sep 28, 2018
1046cfe
Merge branch 'master' of github.com:softlayer/softlayer-python into 1026
allmightyspiff Sep 28, 2018
53492ee
#1026 unit tests and fixtures for ReservedCapacityGroup
allmightyspiff Sep 28, 2018
4815cdb
#1026 unit tests
allmightyspiff Oct 1, 2018
ac15931
#1026 pylint fixes
allmightyspiff Oct 1, 2018
0ac4de3
Merge remote-tracking branch 'origin/master' into 1026
allmightyspiff Oct 3, 2018
87a8ded
doc updates
allmightyspiff Oct 3, 2018
9d87c90
vs capacity docs
allmightyspiff Oct 4, 2018
b2e6784
Fixed an object mask
allmightyspiff Oct 4, 2018
082c1ea
more docs
allmightyspiff Oct 4, 2018
893ff90
fixed whitespace issue
allmightyspiff Oct 4, 2018
3e770a2
Merge branch '1026' of github.com:allmightyspiff/softlayer-python int…
allmightyspiff Oct 8, 2018
03d3c8e
#1026 resolving pull request feedback
allmightyspiff Oct 8, 2018
0d22da9
fixed unit tests
allmightyspiff Oct 8, 2018
4cff83c
some final touches, ended up auto-translating commands so they confor…
allmightyspiff Oct 10, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion SoftLayer/CLI/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def mask(self):
def get_formatter(columns):
"""This function returns a callback to use with click options.

The retuend function parses a comma-separated value and returns a new
The returned function parses a comma-separated value and returns a new
ColumnFormatter.

:param columns: a list of Column instances
Expand Down
1 change: 1 addition & 0 deletions SoftLayer/CLI/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
('virtual:reload', 'SoftLayer.CLI.virt.reload:cli'),
('virtual:upgrade', 'SoftLayer.CLI.virt.upgrade:cli'),
('virtual:credentials', 'SoftLayer.CLI.virt.credentials:cli'),
('virtual:capacity', 'SoftLayer.CLI.virt.capacity:cli'),

('dedicatedhost', 'SoftLayer.CLI.dedicatedhost'),
('dedicatedhost:list', 'SoftLayer.CLI.dedicatedhost.list:cli'),
Expand Down
48 changes: 48 additions & 0 deletions SoftLayer/CLI/virt/capacity/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Manages Reserved Capacity."""
# :license: MIT, see LICENSE for more details.

import importlib
import os

import click

CONTEXT = {'help_option_names': ['-h', '--help'],
'max_content_width': 999}


class CapacityCommands(click.MultiCommand):
"""Loads module for capacity related commands.

Will automatically replace _ with - where appropriate.
I'm not sure if this is better or worse than using a long list of manual routes, so I'm trying it here.
CLI/virt/capacity/create_guest.py -> slcli vs capacity create-guest
"""

def __init__(self, **attrs):
click.MultiCommand.__init__(self, **attrs)
self.path = os.path.dirname(__file__)

def list_commands(self, ctx):
"""List all sub-commands."""
commands = []
for filename in os.listdir(self.path):
if filename == '__init__.py':
continue
if filename.endswith('.py'):
commands.append(filename[:-3].replace("_", "-"))
commands.sort()
return commands

def get_command(self, ctx, cmd_name):
"""Get command for click."""
path = "%s.%s" % (__name__, cmd_name)
path = path.replace("-", "_")
module = importlib.import_module(path)
return getattr(module, 'cli')


# Required to get the sub-sub-sub command to work.
@click.group(cls=CapacityCommands, context_settings=CONTEXT)
def cli():
"""Base command for all capacity related concerns"""
pass
51 changes: 51 additions & 0 deletions SoftLayer/CLI/virt/capacity/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Create a Reserved Capacity instance."""

import click


from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.managers.vs_capacity import CapacityManager as CapacityManager


@click.command(epilog=click.style("""WARNING: Reserved Capacity is on a yearly contract"""
""" and not cancelable until the contract is expired.""", fg='red'))
@click.option('--name', '-n', required=True, prompt=True,
help="Name for your new reserved capacity")
@click.option('--backend_router_id', '-b', required=True, prompt=True, type=int,
help="backendRouterId, create-options has a list of valid ids to use.")
@click.option('--flavor', '-f', required=True, prompt=True,
help="Capacity keyname (C1_2X2_1_YEAR_TERM for example).")
@click.option('--instances', '-i', required=True, prompt=True, type=int,
help="Number of VSI instances this capacity reservation can support.")
@click.option('--test', is_flag=True,
help="Do not actually create the virtual server")
@environment.pass_env
def cli(env, name, backend_router_id, flavor, instances, test=False):
"""Create a Reserved Capacity instance.

*WARNING*: Reserved Capacity is on a yearly contract and not cancelable until the contract is expired.
"""
manager = CapacityManager(env.client)

result = manager.create(
name=name,
backend_router_id=backend_router_id,
flavor=flavor,
instances=instances,
test=test)
if test:
table = formatting.Table(['Name', 'Value'], "Test Order")
container = result['orderContainers'][0]
table.add_row(['Name', container['name']])
table.add_row(['Location', container['locationObject']['longName']])
for price in container['prices']:
table.add_row(['Contract', price['item']['description']])
table.add_row(['Hourly Total', result['postTaxRecurring']])
else:
table = formatting.Table(['Name', 'Value'], "Reciept")
table.add_row(['Order Date', result['orderDate']])
table.add_row(['Order ID', result['orderId']])
table.add_row(['status', result['placedOrder']['status']])
table.add_row(['Hourly Total', result['orderDetails']['postTaxRecurring']])
env.fout(table)
63 changes: 63 additions & 0 deletions SoftLayer/CLI/virt/capacity/create_guest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""List Reserved Capacity"""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.CLI import helpers
from SoftLayer.CLI.virt.create import _parse_create_args as _parse_create_args
from SoftLayer.CLI.virt.create import _update_with_like_args as _update_with_like_args
from SoftLayer.managers.vs_capacity import CapacityManager as CapacityManager


@click.command()
@click.option('--capacity-id', type=click.INT, help="Reserve capacity Id to provision this guest into.")
@click.option('--primary-disk', type=click.Choice(['25', '100']), default='25', help="Size of the main drive.")
@click.option('--hostname', '-H', required=True, prompt=True, help="Host portion of the FQDN.")
@click.option('--domain', '-D', required=True, prompt=True, help="Domain portion of the FQDN.")
@click.option('--os', '-o', help="OS install code. Tip: you can specify <OS>_LATEST.")
@click.option('--image', help="Image ID. See: 'slcli image list' for reference.")
@click.option('--boot-mode', type=click.STRING,
help="Specify the mode to boot the OS in. Supported modes are HVM and PV.")
@click.option('--postinstall', '-i', help="Post-install script to download.")
@helpers.multi_option('--key', '-k', help="SSH keys to add to the root user.")
@helpers.multi_option('--disk', help="Additional disk sizes.")
@click.option('--private', is_flag=True, help="Forces the VS to only have access the private network.")
@click.option('--like', is_eager=True, callback=_update_with_like_args,
help="Use the configuration from an existing VS.")
@click.option('--network', '-n', help="Network port speed in Mbps.")
@helpers.multi_option('--tag', '-g', help="Tags to add to the instance.")
@click.option('--userdata', '-u', help="User defined metadata string.")
@click.option('--ipv6', is_flag=True, help="Adds an IPv6 address to this guest")
@click.option('--test', is_flag=True,
help="Test order, will return the order container, but not actually order a server.")
@environment.pass_env
def cli(env, **args):
"""Allows for creating a virtual guest in a reserved capacity."""
create_args = _parse_create_args(env.client, args)
if args.get('ipv6'):
create_args['ipv6'] = True
create_args['primary_disk'] = args.get('primary_disk')
manager = CapacityManager(env.client)
capacity_id = args.get('capacity_id')
test = args.get('test')

result = manager.create_guest(capacity_id, test, create_args)

env.fout(_build_receipt(result, test))


def _build_receipt(result, test=False):
title = "OrderId: %s" % (result.get('orderId', 'No order placed'))
table = formatting.Table(['Item Id', 'Description'], title=title)
table.align['Description'] = 'l'

if test:
prices = result['prices']
else:
prices = result['orderDetails']['prices']

for item in prices:
table.add_row([item['id'], item['item']['description']])
return table
45 changes: 45 additions & 0 deletions SoftLayer/CLI/virt/capacity/create_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""List options for creating Reserved Capacity"""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.managers.vs_capacity import CapacityManager as CapacityManager


@click.command()
@environment.pass_env
def cli(env):
"""List options for creating Reserved Capacity"""
manager = CapacityManager(env.client)
items = manager.get_create_options()

items.sort(key=lambda term: int(term['capacity']))
table = formatting.Table(["KeyName", "Description", "Term", "Default Hourly Price Per Instance"],
title="Reserved Capacity Options")
table.align["Hourly Price"] = "l"
table.align["Description"] = "l"
table.align["KeyName"] = "l"
for item in items:
table.add_row([
item['keyName'], item['description'], item['capacity'], get_price(item)
])
env.fout(table)

regions = manager.get_available_routers()
location_table = formatting.Table(['Location', 'POD', 'BackendRouterId'], 'Orderable Locations')
for region in regions:
for location in region['locations']:
for pod in location['location']['pods']:
location_table.add_row([region['keyname'], pod['backendRouterName'], pod['backendRouterId']])
env.fout(location_table)


def get_price(item):
"""Finds the price with the default locationGroupId"""
the_price = "No Default Pricing"
for price in item.get('prices', []):
if not price.get('locationGroupId'):
the_price = "%0.4f" % float(price['hourlyRecurringFee'])
return the_price
57 changes: 57 additions & 0 deletions SoftLayer/CLI/virt/capacity/detail.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Shows the details of a reserved capacity group"""

import click

from SoftLayer.CLI import columns as column_helper
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.managers.vs_capacity import CapacityManager as CapacityManager

COLUMNS = [
column_helper.Column('Id', ('id',)),
column_helper.Column('hostname', ('hostname',)),
column_helper.Column('domain', ('domain',)),
column_helper.Column('primary_ip', ('primaryIpAddress',)),
column_helper.Column('backend_ip', ('primaryBackendIpAddress',)),
]

DEFAULT_COLUMNS = [
'id',
'hostname',
'domain',
'primary_ip',
'backend_ip'
]


@click.command(epilog="Once provisioned, virtual guests can be managed with the slcli vs commands")
@click.argument('identifier')
@click.option('--columns',
callback=column_helper.get_formatter(COLUMNS),
help='Columns to display. [options: %s]'
% ', '.join(column.name for column in COLUMNS),
default=','.join(DEFAULT_COLUMNS),
show_default=True)
@environment.pass_env
def cli(env, identifier, columns):
"""Reserved Capacity Group details. Will show which guests are assigned to a reservation."""

manager = CapacityManager(env.client)
mask = """mask[instances[id,createDate,guestId,billingItem[id, description, recurringFee, category[name]],
guest[modifyDate,id, primaryBackendIpAddress, primaryIpAddress,domain, hostname]]]"""
result = manager.get_object(identifier, mask)

try:
flavor = result['instances'][0]['billingItem']['description']
except KeyError:
flavor = "Pending Approval..."

table = formatting.Table(columns.columns, title="%s - %s" % (result.get('name'), flavor))
# RCI = Reserved Capacity Instance
for rci in result['instances']:
guest = rci.get('guest', None)
if guest is not None:
table.add_row([value or formatting.blank() for value in columns.row(guest)])
else:
table.add_row(['-' for value in columns.columns])
env.fout(table)
32 changes: 32 additions & 0 deletions SoftLayer/CLI/virt/capacity/list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""List Reserved Capacity"""

import click

from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.managers.vs_capacity import CapacityManager as CapacityManager


@click.command()
@environment.pass_env
def cli(env):
"""List Reserved Capacity groups."""
manager = CapacityManager(env.client)
result = manager.list()
table = formatting.Table(
["ID", "Name", "Capacity", "Flavor", "Location", "Created"],
title="Reserved Capacity"
)
for r_c in result:
occupied_string = "#" * int(r_c.get('occupiedInstanceCount', 0))
available_string = "-" * int(r_c.get('availableInstanceCount', 0))

try:
flavor = r_c['instances'][0]['billingItem']['description']
# cost = float(r_c['instances'][0]['billingItem']['hourlyRecurringFee'])
except KeyError:
flavor = "Unknown Billing Item"
location = r_c['backendRouter']['hostname']
capacity = "%s%s" % (occupied_string, available_string)
table.add_row([r_c['id'], r_c['name'], capacity, flavor, location, r_c['createDate']])
env.fout(table)
8 changes: 4 additions & 4 deletions SoftLayer/CLI/virt/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ def _parse_create_args(client, args):
:param dict args: CLI arguments
"""
data = {
"hourly": args['billing'] == 'hourly',
"hourly": args.get('billing', 'hourly') == 'hourly',
"domain": args['domain'],
"hostname": args['hostname'],
"private": args['private'],
"dedicated": args['dedicated'],
"private": args.get('private', None),
"dedicated": args.get('dedicated', None),
"disks": args['disk'],
"cpus": args.get('cpu', None),
"memory": args.get('memory', None),
Expand All @@ -89,7 +89,7 @@ def _parse_create_args(client, args):
if not args.get('san') and args.get('flavor'):
data['local_disk'] = None
else:
data['local_disk'] = not args['san']
data['local_disk'] = not args.get('san')

if args.get('os'):
data['os_code'] = args['os']
Expand Down
Loading