Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
65 changes: 38 additions & 27 deletions SoftLayer/managers/ordering.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def get_packages_of_type(self, package_types, mask):
type keynames we are interested in.
:param string mask: Mask to specify the properties we want to retrieve
"""
package_service = self.get_package_service()

package_service = self.client['Product_Package']
_filter = {
'type': {
'keyName': {
Expand All @@ -44,12 +45,6 @@ def get_packages_of_type(self, package_types, mask):
packages = self.filter_outlet_packages(packages)
return packages

def get_package_service(self):
""" Get the service to query product packages
:return SoftLayer.API.Service
"""
return self.client['Product_Package']

@staticmethod
def filter_outlet_packages(packages):
""" Remove packages designated as OUTLET
Expand All @@ -60,6 +55,7 @@ def filter_outlet_packages(packages):
:param packages: Dictionary of packages. Name and description keys
must be present in each of them.
"""

non_outlet_packages = []

for package in packages:
Expand All @@ -78,6 +74,7 @@ def get_only_active_packages(packages):

:param packages Dictionary of packages, isActive key must be present
"""

active_packages = []

for package in packages:
Expand Down Expand Up @@ -110,6 +107,7 @@ def get_package_id_by_type(self, package_type):
we are interested in
:raises ValueError when no package of the given type is found
"""

mask = "mask[id, name, description, isActive, type[keyName]]"
package = self.get_package_by_type(package_type, mask)
if package:
Expand All @@ -119,55 +117,65 @@ def get_package_id_by_type(self, package_type):

def get_quotes(self):
""" Retrieve a list of quotes

:return a list of SoftLayer_Billing_Order_Quote
"""

quotes = self.client['Account'].getActiveQuotes()
return quotes

def get_quote_details(self, quote_id):
""" Retrieve quote details

:param quote_id ID number of target quote
"""

quote = self.client['Billing_Order_Quote'].getObject(id=quote_id)
return quote

def get_order_container(self, quote_id):
""" Generate an order container from a quote object

:param quote_id ID number of target quote
"""

quote = self.client['Billing_Order_Quote']
container = quote.getRecalculatedOrderContainer(id=quote_id)
return container['orderContainers'][0]

def generate_order_template(self, quote_id=None, hostnames=None,
domain=None, quantity=None):
def generate_order_template(self, quote_id, extra, quantity=1):
""" Generate a complete order template

:param int quote_id: ID of target quote
:param list hostnames: List of hostnames as strings
:param string domain: Domain name to be used for all servers
:param int quantity: Quantity to override default
:param list extra: List of dictionaries that have extra details about
the order such as hostname or domain names for
virtual servers or hardware nodes
:param int quantity: Number of ~things~ to order
"""

container = self.get_order_container(quote_id)
if quantity is not None:
container['quantity'] = quantity
container['quantity'] = quantity

# NOTE(kmcdonald): This will only work with virtualGuests and hardware.
# There has to be a better way, since this is based on
# an existing quote that supposedly knows about this
# detail
if container['packageId'] == 46:
product_type = 'virtualGuests'
else:
product_type = 'hardware'

if len(hostnames) != container['quantity']:
raise ValueError("You must specify a hostname for each "
"server in the quote")
if len(extra) != quantity:
raise ValueError("You must specify extra for each server in the "
"quote")

container[product_type] = []
for hostname in hostnames:
container[product_type].append(
{'hostname': hostname, 'domain': domain}
)
for extra_details in extra:
container[product_type].append(extra_details)
container['presetId'] = None
return container

def verify_quote(self, **kwargs):
def verify_quote(self, quote_id, extra, quantity=1):
"""
Verifies that a quote order is valid without actually ordering
the resources
Expand All @@ -177,17 +185,20 @@ def verify_quote(self, **kwargs):
:param string domain: domain of the new servers
:param int quantity: Quantity to override default
"""
container = self.generate_order_template(**kwargs)

container = self.generate_order_template(quote_id, extra,
quantity=quantity)
return self.client['Product_Order'].verifyOrder(container)

def order_quote(self, **kwargs):
"""
Places an order using a quote
def order_quote(self, quote_id, extra, quantity=1):
""" Places an order using a quote

:param int quote_id: ID for the target quote
:param list hostnames: hostnames of the servers
:param string domain: domain of the new server
:param int quantity: Quantity to override default
"""
container = self.generate_order_template(**kwargs)

container = self.generate_order_template(quote_id, extra,
quantity=quantity)
return self.client['Product_Order'].placeOrder(container)
2 changes: 1 addition & 1 deletion SoftLayer/managers/vs.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ def _get_package_items(self):
mask = "mask[description,capacity,prices[id,categories[name,id]]]"
package_type = "VIRTUAL_SERVER_INSTANCE"
package_id = self.ordering_manager.get_package_id_by_type(package_type)
package_service = self.ordering_manager.get_package_service()
package_service = self.client['Product_Package']

return package_service.getItems(id=package_id, mask=mask)

Expand Down
44 changes: 33 additions & 11 deletions SoftLayer/tests/managers/ordering_tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
SoftLayer.tests.managers.ordering_tests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:license: MIT, see LICENSE for more details.
"""
Expand Down Expand Up @@ -83,19 +83,41 @@ def test_get_quotes(self):

def test_get_quote_details(self):
quote = self.ordering.get_quote_details(1234)
quote_fixture = self.ordering.client['Billing_Order_Quote'].getObject(
id=1234)
quote_service = self.ordering.client['Billing_Order_Quote']
quote_fixture = quote_service.getObject(id=1234)
self.assertEqual(quote, quote_fixture)

def test_verify_quote(self):
result = self.ordering.verify_quote(
quote_id=1234,
domain='example.com',
hostnames=['test1'],
quantity=1)
order_service = self.ordering.client['Product_Order']
result = self.ordering.verify_quote(1234,
[{'hostname': 'test1',
'domain': 'example.com'}],
quantity=1)

self.assertEqual(result, self.ordering.client['Product_Order'].
verifyOrder())
self.assertEqual(result, order_service.verifyOrder())
self.assertTrue(order_service.verifyOrder.called)

def test_order_quote(self):
return True
order_service = self.ordering.client['Product_Order']
result = self.ordering.verify_quote(1234,
[{'hostname': 'test1',
'domain': 'example.com'}],
quantity=1)

self.assertEqual(result, order_service.placeOrder())
self.assertTrue(order_service.placeOrder.called)

def test_generate_order_template(self):
result = self.ordering.generate_order_template(
1234, [{'hostname': 'test1', 'domain': 'example.com'}], quantity=1)
self.assertEqual(result, {'presetId': None,
'hardware': [{'domain': 'example.com',
'hostname': 'test1'}],
'useHourlyPricing': '',
'packageId': 50,
'prices': [{'id': 1921}],
'quantity': 1})

def test_generate_order_template_extra_quantity(self):
with self.assertRaises(ValueError):
self.ordering.generate_order_template(1234, [], quantity=1)