Skip to content

Commit

Permalink
Merge pull request #995 from FernandoOjeda/fo_vlan_subnet
Browse files Browse the repository at this point in the history
New Feature to create a vm in a specific subnet
  • Loading branch information
allmightyspiff committed Jul 19, 2018
2 parents aa3879e + 488979b commit 817a9a5
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 15 deletions.
12 changes: 11 additions & 1 deletion SoftLayer/CLI/virt/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ def _parse_create_args(client, args):
if args.get('vlan_private'):
data['private_vlan'] = args['vlan_private']

data['public_subnet'] = args.get('subnet_public', None)

data['private_subnet'] = args.get('subnet_private', None)

if args.get('public_security_group'):
pub_groups = args.get('public_security_group')
data['public_security_groups'] = [group for group in pub_groups]
Expand Down Expand Up @@ -225,12 +229,18 @@ def _parse_create_args(client, args):
type=click.Path(exists=True, readable=True, resolve_path=True))
@click.option('--vlan-public',
help="The ID of the public VLAN on which you want the virtual "
"server placed",
"server placed",
type=click.INT)
@click.option('--vlan-private',
help="The ID of the private VLAN on which you want the virtual "
"server placed",
type=click.INT)
@click.option('--subnet-public',
help="The ID of the public SUBNET on which you want the virtual server placed",
type=click.INT)
@click.option('--subnet-private',
help="The ID of the private SUBNET on which you want the virtual server placed",
type=click.INT)
@helpers.multi_option('--public-security-group',
'-S',
help=('Security group ID to associate with '
Expand Down
39 changes: 30 additions & 9 deletions SoftLayer/managers/vs.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
from SoftLayer.managers import ordering
from SoftLayer import utils


LOGGER = logging.getLogger(__name__)


# pylint: disable=no-self-use


Expand Down Expand Up @@ -305,6 +306,7 @@ def _generate_create_dict(
hostname=None, domain=None, local_disk=True,
datacenter=None, os_code=None, image_id=None,
dedicated=False, public_vlan=None, private_vlan=None,
private_subnet=None, public_subnet=None,
userdata=None, nic_speed=None, disks=None, post_uri=None,
private=False, ssh_keys=None, public_security_groups=None,
private_security_groups=None, boot_mode=None, **kwargs):
Expand Down Expand Up @@ -365,14 +367,10 @@ def _generate_create_dict(
if datacenter:
data["datacenter"] = {"name": datacenter}

if public_vlan:
data.update({
'primaryNetworkComponent': {
"networkVlan": {"id": int(public_vlan)}}})
if private_vlan:
data.update({
"primaryBackendNetworkComponent": {
"networkVlan": {"id": int(private_vlan)}}})
if private_vlan or public_vlan or private_subnet or public_subnet:
network_components = self._create_network_components(public_vlan, private_vlan,
private_subnet, public_subnet)
data.update(network_components)

if public_security_groups:
secgroups = [{'securityGroup': {'id': int(sg)}}
Expand Down Expand Up @@ -415,6 +413,29 @@ def _generate_create_dict(

return data

def _create_network_components(
self, public_vlan=None, private_vlan=None,
private_subnet=None, public_subnet=None):

parameters = {}
if private_vlan:
parameters['primaryBackendNetworkComponent'] = {"networkVlan": {"id": int(private_vlan)}}
if public_vlan:
parameters['primaryNetworkComponent'] = {"networkVlan": {"id": int(public_vlan)}}
if public_subnet:
if public_vlan is None:
raise exceptions.SoftLayerError("You need to specify a public_vlan with public_subnet")
else:
parameters['primaryNetworkComponent']['networkVlan']['primarySubnet'] = {'id': int(public_subnet)}
if private_subnet:
if private_vlan is None:
raise exceptions.SoftLayerError("You need to specify a private_vlan with private_subnet")
else:
parameters['primaryBackendNetworkComponent']['networkVlan']['primarySubnet'] = {
"id": int(private_subnet)}

return parameters

@retry(logger=LOGGER)
def wait_for_transaction(self, instance_id, limit, delay=10):
"""Waits on a VS transaction for the specified amount of time.
Expand Down
25 changes: 25 additions & 0 deletions tests/CLI/modules/vs_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,31 @@ def test_create(self, confirm_mock):
self.assert_called_with('SoftLayer_Virtual_Guest', 'createObject',
args=args)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_create_vlan_subnet(self, confirm_mock):
confirm_mock.return_value = True

result = self.run_command(['vs', 'create',
'--cpu=2',
'--domain=example.com',
'--hostname=host',
'--os=UBUNTU_LATEST',
'--memory=1',
'--billing=hourly',
'--datacenter=dal05',
'--vlan-private=577940',
'--subnet-private=478700',
'--vlan-public=1639255',
'--subnet-public=297614',
'--tag=dev',
'--tag=green'])

self.assert_no_fail(result)
self.assertEqual(json.loads(result.output),
{'guid': '1a2b3c-1701',
'id': 100,
'created': '2013-08-01 15:23:45'})

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_create_with_wait_ready(self, confirm_mock):
mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject')
Expand Down
181 changes: 176 additions & 5 deletions tests/managers/vs_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,116 @@ def test_generate_public_vlan(self):

self.assertEqual(data, assert_data)

def test_generate_public_vlan_with_public_subnet(self):
data = self.vs._generate_create_dict(
cpus=1,
memory=1,
hostname='test',
domain='example.com',
os_code="STRING",
public_vlan=1,
public_subnet=1
)

assert_data = {
'startCpus': 1,
'maxMemory': 1,
'hostname': 'test',
'domain': 'example.com',
'localDiskFlag': True,
'operatingSystemReferenceCode': "STRING",
'hourlyBillingFlag': True,
'primaryNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
'supplementalCreateObjectOptions': {'bootMode': None},
}

self.assertEqual(data, assert_data)

def test_generate_private_vlan_with_private_subnet(self):
data = self.vs._generate_create_dict(
cpus=1,
memory=1,
hostname='test',
domain='example.com',
os_code="STRING",
private_vlan=1,
private_subnet=1
)

assert_data = {
'startCpus': 1,
'maxMemory': 1,
'hostname': 'test',
'domain': 'example.com',
'localDiskFlag': True,
'operatingSystemReferenceCode': "STRING",
'hourlyBillingFlag': True,
'primaryBackendNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
'supplementalCreateObjectOptions': {'bootMode': None},
}

self.assertEqual(data, assert_data)

def test_generate_private_vlan_subnet_public_vlan_subnet(self):
data = self.vs._generate_create_dict(
cpus=1,
memory=1,
hostname='test',
domain='example.com',
os_code="STRING",
private_vlan=1,
private_subnet=1,
public_vlan=1,
public_subnet=1,
)

assert_data = {
'startCpus': 1,
'maxMemory': 1,
'hostname': 'test',
'domain': 'example.com',
'localDiskFlag': True,
'operatingSystemReferenceCode': "STRING",
'hourlyBillingFlag': True,
'primaryBackendNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
'primaryNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
'supplementalCreateObjectOptions': {'bootMode': None},
}

self.assertEqual(data, assert_data)

def test_generate_private_subnet(self):
actual = self.assertRaises(
exceptions.SoftLayerError,
self.vs._generate_create_dict,
cpus=1,
memory=1,
hostname='test',
domain='example.com',
os_code="STRING",
private_subnet=1,
)

self.assertEqual(str(actual), "You need to specify a private_vlan with private_subnet")

def test_generate_public_subnet(self):
actual = self.assertRaises(
exceptions.SoftLayerError,
self.vs._generate_create_dict,
cpus=1,
memory=1,
hostname='test',
domain='example.com',
os_code="STRING",
public_subnet=1,
)

self.assertEqual(str(actual), "You need to specify a public_vlan with public_subnet")

def test_generate_private_vlan(self):
data = self.vs._generate_create_dict(
cpus=1,
Expand All @@ -373,12 +483,73 @@ def test_generate_private_vlan(self):
'localDiskFlag': True,
'operatingSystemReferenceCode': "STRING",
'hourlyBillingFlag': True,
'primaryBackendNetworkComponent': {"networkVlan": {"id": 1}},
'primaryBackendNetworkComponent': {'networkVlan': {'id': 1}},
'supplementalCreateObjectOptions': {'bootMode': None},
}

self.assertEqual(data, assert_data)

def test_create_network_components_vlan_subnet_private_vlan_subnet_public(self):
data = self.vs._create_network_components(
private_vlan=1,
private_subnet=1,
public_vlan=1,
public_subnet=1,
)

assert_data = {
'primaryBackendNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
'primaryNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
}

self.assertEqual(data, assert_data)

def test_create_network_components_vlan_subnet_private(self):
data = self.vs._create_network_components(
private_vlan=1,
private_subnet=1,
)

assert_data = {
'primaryBackendNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
}

self.assertEqual(data, assert_data)

def test_create_network_components_vlan_subnet_public(self):
data = self.vs._create_network_components(
public_vlan=1,
public_subnet=1,
)

assert_data = {
'primaryNetworkComponent': {'networkVlan': {'id': 1,
'primarySubnet': {'id': 1}}},
}

self.assertEqual(data, assert_data)

def test_create_network_components_private_subnet(self):
actual = self.assertRaises(
exceptions.SoftLayerError,
self.vs._create_network_components,
private_subnet=1,
)

self.assertEqual(str(actual), "You need to specify a private_vlan with private_subnet")

def test_create_network_components_public_subnet(self):
actual = self.assertRaises(
exceptions.SoftLayerError,
self.vs._create_network_components,
public_subnet=1,
)

self.assertEqual(str(actual), "You need to specify a public_vlan with public_subnet")

def test_generate_userdata(self):
data = self.vs._generate_create_dict(
cpus=1,
Expand Down Expand Up @@ -621,10 +792,10 @@ def test_edit_full(self):

self.assertEqual(result, True)
args = ({
'hostname': 'new-host',
'domain': 'new.sftlyr.ws',
'notes': 'random notes',
},)
'hostname': 'new-host',
'domain': 'new.sftlyr.ws',
'notes': 'random notes',
},)
self.assert_called_with('SoftLayer_Virtual_Guest', 'editObject',
identifier=100,
args=args)
Expand Down

0 comments on commit 817a9a5

Please sign in to comment.