Skip to content

Commit 39f9e1b

Browse files
support for creating guests, some more features for list and detail
1 parent 87b51a9 commit 39f9e1b

File tree

5 files changed

+230
-819
lines changed

5 files changed

+230
-819
lines changed

SoftLayer/CLI/virt/capacity/create-guest.py

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,138 @@
66
import SoftLayer
77
from SoftLayer.CLI import environment
88
from SoftLayer.CLI import formatting
9+
from SoftLayer.CLI import helpers
10+
from SoftLayer.CLI.virt.create import _update_with_like_args as _update_with_like_args
911
from SoftLayer.managers.vs_capacity import CapacityManager as CapacityManager
1012

1113

1214
from pprint import pprint as pp
1315

16+
17+
18+
def _parse_create_args(client, args):
19+
"""Parses CLI arguments into a single data structure to be used by vs_capacity::create_guest.
20+
21+
:param dict args: CLI arguments
22+
"""
23+
data = {
24+
"hourly": True,
25+
"domain": args['domain'],
26+
"hostname": args['hostname'],
27+
"private": args['private'],
28+
"disks": args['disk'],
29+
"boot_mode": args.get('boot_mode', None),
30+
"local_disk": None
31+
}
32+
if args.get('os'):
33+
data['os_code'] = args['os']
34+
35+
if args.get('image'):
36+
if args.get('image').isdigit():
37+
image_mgr = SoftLayer.ImageManager(client)
38+
image_details = image_mgr.get_image(args.get('image'),
39+
mask="id,globalIdentifier")
40+
data['image_id'] = image_details['globalIdentifier']
41+
else:
42+
data['image_id'] = args['image']
43+
44+
if args.get('network'):
45+
data['nic_speed'] = args.get('network')
46+
47+
if args.get('userdata'):
48+
data['userdata'] = args['userdata']
49+
elif args.get('userfile'):
50+
with open(args['userfile'], 'r') as userfile:
51+
data['userdata'] = userfile.read()
52+
53+
if args.get('postinstall'):
54+
data['post_uri'] = args.get('postinstall')
55+
56+
# Get the SSH keys
57+
if args.get('key'):
58+
keys = []
59+
for key in args.get('key'):
60+
resolver = SoftLayer.SshKeyManager(client).resolve_ids
61+
key_id = helpers.resolve_id(resolver, key, 'SshKey')
62+
keys.append(key_id)
63+
data['ssh_keys'] = keys
64+
65+
if args.get('vlan_public'):
66+
data['public_vlan'] = args['vlan_public']
67+
68+
if args.get('vlan_private'):
69+
data['private_vlan'] = args['vlan_private']
70+
71+
data['public_subnet'] = args.get('subnet_public', None)
72+
73+
data['private_subnet'] = args.get('subnet_private', None)
74+
75+
if args.get('public_security_group'):
76+
pub_groups = args.get('public_security_group')
77+
data['public_security_groups'] = [group for group in pub_groups]
78+
79+
if args.get('private_security_group'):
80+
priv_groups = args.get('private_security_group')
81+
data['private_security_groups'] = [group for group in priv_groups]
82+
83+
if args.get('tag'):
84+
data['tags'] = ','.join(args['tag'])
85+
86+
if args.get('host_id'):
87+
data['host_id'] = args['host_id']
88+
89+
if args.get('ipv6'):
90+
data['ipv6'] = True
91+
92+
data['primary_disk'] = args.get('primary_disk')
93+
94+
return data
95+
96+
1497
@click.command()
98+
@click.option('--capacity-id', type=click.INT, help="Reserve capacity Id to provision this guest into.")
99+
@click.option('--primary-disk', type=click.Choice(['25','100']), default='25', help="Size of the main drive." )
100+
@click.option('--hostname', '-H', required=True, prompt=True, help="Host portion of the FQDN.")
101+
@click.option('--domain', '-D', required=True, prompt=True, help="Domain portion of the FQDN.")
102+
@click.option('--os', '-o', help="OS install code. Tip: you can specify <OS>_LATEST.")
103+
@click.option('--image', help="Image ID. See: 'slcli image list' for reference.")
104+
@click.option('--boot-mode', type=click.STRING,
105+
help="Specify the mode to boot the OS in. Supported modes are HVM and PV.")
106+
@click.option('--postinstall', '-i', help="Post-install script to download.")
107+
@helpers.multi_option('--key', '-k', help="SSH keys to add to the root user.")
108+
@helpers.multi_option('--disk', help="Additional disk sizes.")
109+
@click.option('--private', is_flag=True, help="Forces the VS to only have access the private network.")
110+
@click.option('--like', is_eager=True, callback=_update_with_like_args,
111+
help="Use the configuration from an existing VS.")
112+
@click.option('--network', '-n', help="Network port speed in Mbps.")
113+
@helpers.multi_option('--tag', '-g', help="Tags to add to the instance.")
114+
@click.option('--userdata', '-u', help="User defined metadata string.")
115+
@click.option('--ipv6', is_flag=True, help="Adds an IPv6 address to this guest")
116+
@click.option('--test', is_flag=True,
117+
help="Test order, will return the order container, but not actually order a server.")
15118
@environment.pass_env
16-
def cli(env):
17-
print("This is where you would create a guest")
119+
def cli(env, **args):
120+
create_args = _parse_create_args(env.client, args)
121+
manager = CapacityManager(env.client)
122+
capacity_id = args.get('capacity_id')
123+
test = args.get('test')
124+
125+
result = manager.create_guest(capacity_id, test, create_args)
126+
127+
env.fout(_build_receipt(result, test))
128+
129+
130+
def _build_receipt(result, test=False):
131+
title = "OrderId: %s" % (result.get('orderId', 'No order placed'))
132+
table = formatting.Table(['Item Id', 'Description'], title=title)
133+
table.align['Description'] = 'l'
134+
135+
if test:
136+
prices = result['prices']
137+
else:
138+
prices = result['orderDetails']['prices']
139+
140+
for item in prices:
141+
table.add_row([item['id'], item['item']['description']])
142+
return table
143+

SoftLayer/CLI/virt/capacity/create.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
from pprint import pprint as pp
1313

14-
@click.command(epilog="See 'slcli vs capacity create-options' for valid options")
14+
@click.command(epilog=click.style("""WARNING: Reserved Capacity is on a yearly contract"""
15+
""" and not cancelable until the contract is expired.""", fg='red'))
1516
@click.option('--name', '-n', required=True, prompt=True,
1617
help="Name for your new reserved capacity")
1718
@click.option('--datacenter', '-d', required=True, prompt=True,

SoftLayer/CLI/virt/capacity/detail.py

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,74 @@
44
import click
55

66
import SoftLayer
7+
from SoftLayer.CLI import columns as column_helper
78
from SoftLayer.CLI import environment
89
from SoftLayer.CLI import formatting
910
from SoftLayer.managers.vs_capacity import CapacityManager as CapacityManager
1011

12+
COLUMNS = [
13+
column_helper.Column('guid', ('globalIdentifier',)),
14+
column_helper.Column('primary_ip', ('primaryIpAddress',)),
15+
column_helper.Column('backend_ip', ('primaryBackendIpAddress',)),
16+
column_helper.Column('datacenter', ('datacenter', 'name')),
17+
column_helper.Column('action', lambda guest: formatting.active_txn(guest),
18+
mask='''
19+
activeTransaction[
20+
id,transactionStatus[name,friendlyName]
21+
]'''),
22+
column_helper.Column('power_state', ('powerState', 'name')),
23+
column_helper.Column(
24+
'created_by',
25+
('billingItem', 'orderItem', 'order', 'userRecord', 'username')),
26+
column_helper.Column(
27+
'tags',
28+
lambda server: formatting.tags(server.get('tagReferences')),
29+
mask="tagReferences.tag.name"),
30+
]
1131

12-
from pprint import pprint as pp
32+
DEFAULT_COLUMNS = [
33+
'id',
34+
'hostname',
35+
'domain',
36+
'primary_ip',
37+
'backend_ip'
38+
]
1339

14-
@click.command()
40+
@click.command(epilog="Once provisioned, virtual guests can be managed with the slcli vs commands")
1541
@click.argument('identifier')
42+
@click.option('--columns',
43+
callback=column_helper.get_formatter(COLUMNS),
44+
help='Columns to display. [options: %s]'
45+
% ', '.join(column.name for column in COLUMNS),
46+
default=','.join(DEFAULT_COLUMNS),
47+
show_default=True)
1648
@environment.pass_env
17-
def cli(env, identifier):
49+
def cli(env, identifier, columns):
1850
"""Reserved Capacity Group Details"""
1951
manager = CapacityManager(env.client)
20-
result = manager.get_object(identifier)
52+
mask = "mask[instances[billingItem[category], guest]]"
53+
result = manager.get_object(identifier, mask)
2154
try:
2255
flavor = result['instances'][0]['billingItem']['description']
2356
except KeyError:
2457
flavor = "Pending Approval..."
2558

26-
table = formatting.Table(
27-
["ID", "Created"],
28-
title= "%s - %s" % (result.get('name'), flavor)
59+
table = formatting.Table(columns.columns,
60+
title = "%s - %s" % (result.get('name'), flavor)
2961
)
3062
for rci in result['instances']:
31-
table.add_row([rci['guestId'], rci['createDate']])
63+
guest = rci.get('guest', None)
64+
guest_string = "---"
65+
createDate = rci['createDate']
66+
if guest is not None:
67+
guest_string = "%s (%s)" % (
68+
guest.get('fullyQualifiedDomainName', 'No FQDN'),
69+
guest.get('primaryIpAddress', 'No Public Ip')
70+
)
71+
createDate = guest['modifyDate']
72+
table.add_row([value or formatting.blank() for value in columns.row(guest)])
73+
else:
74+
table.add_row(['-' for value in columns.columns])
3275
env.fout(table)
3376

77+

SoftLayer/CLI/virt/capacity/list.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,24 @@ def cli(env):
1818
manager = CapacityManager(env.client)
1919
result = manager.list()
2020
table = formatting.Table(
21-
["ID", "Name", "Capacity", "Flavor", "Instance Cost", "Created"],
21+
["ID", "Name", "Capacity", "Flavor", "Location", "Created"],
2222
title="Reserved Capacity"
2323
)
2424
for rc in result:
25-
occupied_string = "#" * int(rc.get('occupiedInstancesCount',0))
25+
occupied_string = "#" * int(rc.get('occupiedInstanceCount',0))
2626
available_string = "-" * int(rc.get('availableInstanceCount',0))
2727

2828
try:
2929
flavor = rc['instances'][0]['billingItem']['description']
3030
cost = float(rc['instances'][0]['billingItem']['hourlyRecurringFee'])
31-
instance_count = int(rc.get('instanceCount',0))
32-
cost_string = "%s * %s = %s" % (cost, instance_count, cost * instance_count)
31+
# instance_count = int(rc.get('instanceCount',0))
32+
# cost_string = "%s * %s = %s" % (cost, instance_count, cost * instance_count)
3333
except KeyError:
3434
flavor = "Unknown Billing Item"
35-
cost_string = "-"
35+
# cost_string = "-"
36+
location = rc['backendRouter']['hostname']
3637
capacity = "%s%s" % (occupied_string, available_string)
37-
table.add_row([rc['id'], rc['name'], capacity, flavor, cost_string, rc['createDate']])
38+
table.add_row([rc['id'], rc['name'], capacity, flavor, location, rc['createDate']])
3839
env.fout(table)
39-
pp(result)
40+
print("")
41+
# pp(result)

0 commit comments

Comments
 (0)