Skip to content
Merged
2 changes: 2 additions & 0 deletions SoftLayer/CLI/dedicatedhost/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"""Dedicated Host."""
# :license: MIT, see LICENSE for more details.
114 changes: 114 additions & 0 deletions SoftLayer/CLI/dedicatedhost/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""Order/create a dedicated Host."""
# :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 template


@click.command(
epilog="See 'slcli dedicatedhost create-options' for valid options.")
@click.option('--hostname', '-H',
help="Host portion of the FQDN",
required=True,
prompt=True)
@click.option('--router', '-r',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. unless its wildly complicated, I would prefer to pass in the router hostname, fcr02a.dal13 or something
  2. Is specifying a VLAN not an option for dedicated hosts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Specifying a VLAN is not an option for dedicated hosts

help="Router hostname ex. fcr02a.dal13",
show_default=True)
@click.option('--domain', '-D',
help="Domain portion of the FQDN",
required=True,
prompt=True)
@click.option('--datacenter', '-d', help="Datacenter shortname",
required=True,
prompt=True)
@click.option('--flavor', '-f', help="Dedicated Virtual Host flavor",
required=True,
prompt=True)
@click.option('--billing',
type=click.Choice(['hourly', 'monthly']),
default='hourly',
show_default=True,
help="Billing rate")
@click.option('--verify',
is_flag=True,
help="Verify dedicatedhost without creating it.")
@click.option('--template', '-t',
is_eager=True,
callback=template.TemplateCallback(list_args=['key']),
help="A template file that defaults the command-line options",
type=click.Path(exists=True, readable=True, resolve_path=True))
@click.option('--export',
type=click.Path(writable=True, resolve_path=True),
help="Exports options to a template file")
@environment.pass_env
def cli(env, **kwargs):
"""Order/create a dedicated host."""
mgr = SoftLayer.DedicatedHostManager(env.client)

order = {
'hostname': kwargs['hostname'],
'domain': kwargs['domain'],
'flavor': kwargs['flavor'],
'location': kwargs['datacenter'],
'hourly': kwargs.get('billing') == 'hourly',
}

if kwargs['router']:
order['router'] = kwargs['router']

do_create = not (kwargs['export'] or kwargs['verify'])

output = None

result = mgr.verify_order(**order)
table = formatting.Table(['Item', 'cost'])
table.align['Item'] = 'r'
table.align['cost'] = 'r'
if len(result['prices']) != 1:
raise exceptions.ArgumentError("More than 1 price was found or no "
"prices found")
price = result['prices']

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set price = result['prices'][0] here, because price[0] looks weird down below (and you're doing it twice so that helps clean up the below a little more)

if order['hourly']:
total = float(price[0].get('hourlyRecurringFee', 0.0))
else:
total = float(price[0].get('recurringFee', 0.0))

if order['hourly']:
table.add_row(['Total hourly cost', "%.2f" % total])
else:
table.add_row(['Total monthly cost', "%.2f" % total])

output = []
output.append(table)
output.append(formatting.FormattedItem(
'',
' -- ! Prices reflected here are retail and do not '
'take account level discounts and are not guaranteed.'))

if kwargs['export']:
export_file = kwargs.pop('export')
template.export_to_template(export_file, kwargs,
exclude=['wait', 'verify'])
env.fout('Successfully exported options to a template file.')

if do_create:
if not env.skip_confirmations and not formatting.confirm(
"This action will incur charges on your account. "
"Continue?"):
raise exceptions.CLIAbort('Aborting dedicated host order.')

result = mgr.place_order(**order)

table = formatting.KeyValueTable(['name', 'value'])
table.align['name'] = 'r'
table.align['value'] = 'l'
table.add_row(['id', result['orderId']])
table.add_row(['created', result['orderDate']])
output.append(table)

env.fout(output)
61 changes: 61 additions & 0 deletions SoftLayer/CLI/dedicatedhost/create_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Options for ordering a dedicated host"""
# :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.option('--datacenter', '-d',
help="Router hostname (requires --flavor) "
"ex. ams01",
show_default=True)
@click.option('--flavor', '-f',
help="Dedicated Virtual Host flavor (requires --datacenter)"
" ex. 56_CORES_X_242_RAM_X_1_4_TB",
show_default=True)
@environment.pass_env
def cli(env, **kwargs):
"""host order options for a given dedicated host.

To get a list of available backend routers see example:
slcli dh create-options --datacenter dal05 --flavor 56_CORES_X_242_RAM_X_1_4_TB
"""

mgr = SoftLayer.DedicatedHostManager(env.client)
tables = []

if not kwargs['flavor'] and not kwargs['datacenter']:
options = mgr.get_create_options()

# Datacenters
dc_table = formatting.Table(['datacenter', 'value'])
dc_table.sortby = 'value'
for location in options['locations']:
dc_table.add_row([location['name'], location['key']])
tables.append(dc_table)

dh_table = formatting.Table(['Dedicated Virtual Host Flavor(s)', 'value'])
dh_table.sortby = 'value'
for item in options['dedicated_host']:
dh_table.add_row([item['name'], item['key']])
tables.append(dh_table)
else:
if kwargs['flavor'] is None or kwargs['datacenter'] is None:
raise exceptions.ArgumentError('Both a flavor and datacenter need '
'to be passed as arguments '
'ex. slcli dh create-options -d '
'ams01 -f '
'56_CORES_X_242_RAM_X_1_4_TB')
router_opt = mgr.get_router_options(kwargs['datacenter'], kwargs['flavor'])
br_table = formatting.Table(
['Available Backend Routers'])
for router in router_opt:
br_table.add_row([router['hostname']])
tables.append(br_table)

env.fout(formatting.listing(tables, separator='\n'))
65 changes: 65 additions & 0 deletions SoftLayer/CLI/dedicatedhost/detail.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Get details for a dedicated host."""
# :license: MIT, see LICENSE for more details.

import logging

import click

import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer import utils

LOGGER = logging.getLogger(__name__)


@click.command()
@click.argument('identifier')
@click.option('--price', is_flag=True, help='Show associated prices')
@click.option('--guests', is_flag=True, help='Show guests on dedicated host')
@environment.pass_env
def cli(env, identifier, price=False, guests=False):
"""Get details for a virtual server."""
dhost = SoftLayer.DedicatedHostManager(env.client)

table = formatting.KeyValueTable(['name', 'value'])
table.align['name'] = 'r'
table.align['value'] = 'l'

result = dhost.get_host(identifier)
result = utils.NestedDict(result)

table.add_row(['id', result['id']])
table.add_row(['name', result['name']])
table.add_row(['cpu count', result['cpuCount']])
table.add_row(['memory capacity', result['memoryCapacity']])
table.add_row(['disk capacity', result['diskCapacity']])
table.add_row(['create date', result['createDate']])
table.add_row(['modify date', result['modifyDate']])
table.add_row(['router id', result['backendRouter']['id']])
table.add_row(['router hostname', result['backendRouter']['hostname']])
table.add_row(['owner', formatting.FormattedItem(
utils.lookup(result, 'billingItem', 'orderItem', 'order', 'userRecord', 'username') or formatting.blank(),)])

if price:
total_price = utils.lookup(result,
'billingItem',
'nextInvoiceTotalRecurringAmount') or 0
total_price += sum(p['nextInvoiceTotalRecurringAmount']
for p
in utils.lookup(result,
'billingItem',
'children') or [])
table.add_row(['price_rate', total_price])

table.add_row(['guest count', result['guestCount']])
if guests:
guest_table = formatting.Table(['id', 'hostname', 'domain', 'uuid'])
for guest in result['guests']:
guest_table.add_row([
guest['id'], guest['hostname'], guest['domain'], guest['uuid']])
table.add_row(['guests', guest_table])

table.add_row(['datacenter', result['datacenter']['name']])

env.fout(table)
70 changes: 70 additions & 0 deletions SoftLayer/CLI/dedicatedhost/list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""List dedicated servers."""
# :license: MIT, see LICENSE for more details.

import click

import SoftLayer
from SoftLayer.CLI import columns as column_helper
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.CLI import helpers

COLUMNS = [
column_helper.Column('datacenter', ('datacenter', 'name')),
column_helper.Column(
'created_by',
('billingItem', 'orderItem', 'order', 'userRecord', 'username')),
column_helper.Column(
'tags',
lambda server: formatting.tags(server.get('tagReferences')),
mask="tagReferences.tag.name"),
]

DEFAULT_COLUMNS = [
'id',
'name',
'cpuCount',
'diskCapacity',
'memoryCapacity',
'datacenter',
'guestCount',
]


@click.command()
@click.option('--cpu', '-c', help='Number of CPU cores', type=click.INT)
@helpers.multi_option('--tag', help='Filter by tags')
@click.option('--sortby', help='Column to sort by',
default='name',
show_default=True)
@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)
@click.option('--datacenter', '-d', help='Datacenter shortname')
@click.option('--name', '-H', help='Host portion of the FQDN')
@click.option('--memory', '-m', help='Memory capacity in mebibytes',
type=click.INT)
@click.option('--disk', '-D', help='Disk capacity')
@environment.pass_env
def cli(env, sortby, cpu, columns, datacenter, name, memory, disk, tag):
"""List dedicated host."""
mgr = SoftLayer.DedicatedHostManager(env.client)
hosts = mgr.list_instances(cpus=cpu,
datacenter=datacenter,
hostname=name,
memory=memory,
disk=disk,
tags=tag,
mask=columns.mask())

table = formatting.Table(columns.columns)
table.sortby = sortby

for host in hosts:
table.add_row([value or formatting.blank()
for value in columns.row(host)])

env.fout(table)
7 changes: 7 additions & 0 deletions SoftLayer/CLI/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
('virtual:upgrade', 'SoftLayer.CLI.virt.upgrade:cli'),
('virtual:credentials', 'SoftLayer.CLI.virt.credentials:cli'),

('dedicatedhost', 'SoftLayer.CLI.dedicatedhost'),
('dedicatedhost:list', 'SoftLayer.CLI.dedicatedhost.list:cli'),
('dedicatedhost:create', 'SoftLayer.CLI.dedicatedhost.create:cli'),
('dedicatedhost:create-options', 'SoftLayer.CLI.dedicatedhost.create_options:cli'),
('dedicatedhost:detail', 'SoftLayer.CLI.dedicatedhost.detail:cli'),

('cdn', 'SoftLayer.CLI.cdn'),
('cdn:detail', 'SoftLayer.CLI.cdn.detail:cli'),
('cdn:list', 'SoftLayer.CLI.cdn.list:cli'),
Expand Down Expand Up @@ -280,4 +286,5 @@
'server': 'hardware',
'vm': 'virtual',
'vs': 'virtual',
'dh': 'dedicatedhost',
}
14 changes: 12 additions & 2 deletions SoftLayer/fixtures/SoftLayer_Account.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
getHourlyVirtualGuests = [vs for vs in getVirtualGuests
if vs['hourlyBillingFlag']]


getHardware = [{
'id': 1000,
'metricTrackingObject': {'id': 3},
Expand Down Expand Up @@ -488,7 +487,6 @@
'quoteKey': '1234test4321',
}]


getOrders = [{
'id': 1234,
'resourceType': '1 x 2.0 GHz Core',
Expand Down Expand Up @@ -548,3 +546,15 @@
'name': 'my first pool',
'metricTrackingObjectId': 10,
}]

getDedicatedHosts = [{
'datacenter': {
'name': 'dal05'
},
'memoryCapacity': 242,
'name': 'khnguyendh',
'diskCapacity': 1200,
'guestCount': 1,
'cpuCount': 56,
'id': 44701
}]
Loading