Repository: softlayer/softlayer-python
Pull request #1698 (2022-07-18 14:00:56)

New command ipsec order
[#issue1696](https://github.com/softlayer/softlayer-python/issues/1696)


![image](https://user-images.githubusercontent.com/22535437/179528291-9a56e08a-7190-4050-bda0-650ab99c1ca9.png)



Patch:
diff --git a/SoftLayer/CLI/block/options.py b/SoftLayer/CLI/block/options.py
deleted file mode 100644
index 7a020d68..00000000
--- a/SoftLayer/CLI/block/options.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""List all options for ordering a block storage."""
-# :license: MIT, see LICENSE for more details.
-
-import click
-
-import SoftLayer
-from SoftLayer.CLI.command import SLCommand
-from SoftLayer.CLI import environment
-from SoftLayer.CLI import formatting
-
-PACKAGE_STORAGE = 759
-
-
-@click.command(cls=SLCommand)
-@environment.pass_env
-def cli(env):
-    """List all options for ordering a block storage"""
-
-    order_manager = SoftLayer.OrderingManager(env.client)
-    items = order_manager.get_items(PACKAGE_STORAGE)
-    datacenters = order_manager.get_regions(PACKAGE_STORAGE)
-
-    iops_table = formatting.Table(['Id', 'Description', 'KeyName'], title='IOPS')
-    snapshot_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Snapshot')
-    storage_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Storage')
-    datacenter_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Datacenter')
-
-    for datacenter in datacenters:
-        datacenter_table.add_row([datacenter['location']['locationId'],
-                                  datacenter.get('description'),
-                                  datacenter['keyname']])
-
-    for item in items:
-        if item['itemCategory']['categoryCode'] == 'performance_storage_space':
-            storage_table.add_row([item.get('id'), item.get('description'),
-                                   item.get('keyName')])
-
-        if item['itemCategory']['categoryCode'] == 'storage_tier_level':
-            iops_table.add_row([item.get('id'), item.get('description'),
-                                item.get('keyName')])
-
-        if item['itemCategory']['categoryCode'] == 'storage_snapshot_space':
-            snapshot_table.add_row([item.get('id'), item.get('description'),
-                                    item.get('keyName')])
-
-    env.fout(datacenter_table)
-    env.fout(iops_table)
-    env.fout(storage_table)
-    env.fout(snapshot_table)
diff --git a/SoftLayer/CLI/environment.py b/SoftLayer/CLI/environment.py
index d7b98501..0c4d17b2 100644
--- a/SoftLayer/CLI/environment.py
+++ b/SoftLayer/CLI/environment.py
@@ -45,10 +45,6 @@ def __init__(self):
 
     def out(self, output):
         """Outputs a string to the console (stdout)."""
-
-        # If we output to a | or file, need to set default width so all output is printed.
-        if not self.console.is_terminal:
-            self.console.width = 1000000
         if self.format == 'json':
             try:
                 self.console.print_json(output)
diff --git a/SoftLayer/CLI/file/options.py b/SoftLayer/CLI/file/options.py
deleted file mode 100644
index f2ca734b..00000000
--- a/SoftLayer/CLI/file/options.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""List all options for ordering a file storage."""
-# :license: MIT, see LICENSE for more details.
-
-import click
-
-import SoftLayer
-from SoftLayer.CLI.command import SLCommand
-from SoftLayer.CLI import environment
-from SoftLayer.CLI import formatting
-
-
-PACKAGE_STORAGE = 759
-
-
-@click.command(cls=SLCommand)
-@environment.pass_env
-def cli(env):
-    """List all options for ordering a file storage"""
-
-    order_manager = SoftLayer.OrderingManager(env.client)
-    items = order_manager.get_items(PACKAGE_STORAGE)
-    datacenters = order_manager.get_regions(PACKAGE_STORAGE)
-
-    iops_table = formatting.Table(['Id', 'Description', 'KeyName'], title='IOPS')
-    snapshot_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Snapshot')
-    storage_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Storage')
-    datacenter_table = formatting.Table(['Id', 'Description', 'KeyName'], title='Datacenter')
-
-    for datacenter in datacenters:
-        datacenter_table.add_row([datacenter['location']['locationId'],
-                                  datacenter.get('description'),
-                                  datacenter['keyname']])
-
-    for item in items:
-        if item['itemCategory']['categoryCode'] == 'performance_storage_space':
-            storage_table.add_row([item.get('id'), item.get('description'),
-                                   item.get('keyName')])
-
-        if item['itemCategory']['categoryCode'] == 'storage_tier_level':
-            iops_table.add_row([item.get('id'), item.get('description'),
-                                item.get('keyName')])
-
-        if item['itemCategory']['categoryCode'] == 'storage_snapshot_space':
-            snapshot_table.add_row([item.get('id'), item.get('description'),
-                                    item.get('keyName')])
-
-    env.fout(datacenter_table)
-    env.fout(iops_table)
-    env.fout(storage_table)
-    env.fout(snapshot_table)
diff --git a/SoftLayer/CLI/formatting.py b/SoftLayer/CLI/formatting.py
index 02781fcf..afe25fff 100644
--- a/SoftLayer/CLI/formatting.py
+++ b/SoftLayer/CLI/formatting.py
@@ -35,7 +35,7 @@ def format_output(data, fmt='table'):  # pylint: disable=R0911,R0912
 
     # responds to .prettytable()
     if hasattr(data, 'prettytable') and fmt in ('table', 'raw'):
-        return format_prettytable(data, fmt)
+        return format_prettytable(data)
 
     # responds to .to_python()
     if hasattr(data, 'to_python'):
@@ -68,17 +68,12 @@ def format_output(data, fmt='table'):  # pylint: disable=R0911,R0912
     return str(data)
 
 
-def format_prettytable(table, fmt='table'):
+def format_prettytable(table):
     """Converts SoftLayer.CLI.formatting.Table instance to a prettytable."""
     for i, row in enumerate(table.rows):
         for j, item in enumerate(row):
-            # Issue when adding items that evaulate to None (like empty lists) for Rich Tables
-            # so we just cast those to a str
-            if item:
-                table.rows[i][j] = format_output(item)
-            else:
-                table.rows[i][j] = str(item)
-    ptable = table.prettytable(fmt)
+            table.rows[i][j] = format_output(item)
+    ptable = table.prettytable()
     return ptable
 
 
@@ -213,6 +208,7 @@ def to_python(self):
         return self
 
     def __str__(self):
+        print("CASTSDFSDFSDFSDFSDF")
         return self.separator.join(str(x) for x in self)
 
 
@@ -262,12 +258,9 @@ def to_python(self):
             items.append(dict(zip(self.columns, formatted_row)))
         return items
 
-    def prettytable(self, fmt='table'):
+    def prettytable(self):
         """Returns a RICH table instance."""
-        box_style = box.SQUARE
-        if fmt == 'raw':
-            box_style = None
-        table = rTable(title=self.title, box=box_style, header_style="bright_cyan")
+        table = rTable(title=self.title, box=box.SQUARE, header_style="bright_cyan")
         if self.sortby:
             try:
                 # https://docs.python.org/3/howto/sorting.html#key-functions
diff --git a/SoftLayer/CLI/hardware/create.py b/SoftLayer/CLI/hardware/create.py
index 682c07be..52ebfa5c 100644
--- a/SoftLayer/CLI/hardware/create.py
+++ b/SoftLayer/CLI/hardware/create.py
@@ -44,6 +44,7 @@ def cli(env, **args):
     network = SoftLayer.NetworkManager(env.client)
 
     pods = network.get_closed_pods()
+    closure = []
 
     # Get the SSH keys
     ssh_keys = []
@@ -103,8 +104,9 @@ def cli(env, **args):
 
     if do_create:
         for pod in pods:
-            if args.get('datacenter') in pod['name']:
-                click.secho('Warning: Closed soon: {}'.format(pod['name']), fg='yellow')
+            if args.get('datacenter') in str(pod['name']):
+                closure.append(pod['name'])
+        click.secho(click.style('Warning: Closed soon: %s' % (', '.join(closure)), fg='yellow'))
         if not (env.skip_confirmations or formatting.confirm(
                 "This action will incur charges on your account. Continue?")):
             raise exceptions.CLIAbort('Aborting dedicated server order.')
diff --git a/SoftLayer/CLI/hardware/sensor.py b/SoftLayer/CLI/hardware/sensor.py
index 9f9d3da4..858d2584 100644
--- a/SoftLayer/CLI/hardware/sensor.py
+++ b/SoftLayer/CLI/hardware/sensor.py
@@ -16,16 +16,16 @@ def cli(env, identifier, discrete):
     mgr = SoftLayer.HardwareManager(env.client)
     sensors = mgr.get_sensors(identifier)
 
-    temperature_table = formatting.Table(["Sensor", "Status", "Reading", "Critical Min", "Min", "Max", "Critical Max"],
+    temperature_table = formatting.Table(["Sensor", "Status", "Reading", "Min", "Max"],
                                          title='Temperature (c)')
 
-    volts_table = formatting.Table(["Sensor", "Status", "Reading", "Critical Min", "Min", "Max", "Critical Max"],
+    volts_table = formatting.Table(["Sensor", "Status", "Reading", "Min", "Max"],
                                    title='Volts')
 
-    watts_table = formatting.Table(["Sensor", "Status", "Reading", "Critical Min", "Min", "Max", "Critical Max"],
+    watts_table = formatting.Table(["Sensor", "Status", "Reading"],
                                    title='Watts')
 
-    rpm_table = formatting.Table(["Sensor", "Status", "Reading", "Critical Min", "Min", "Max", "Critical Max"],
+    rpm_table = formatting.Table(["Sensor", "Status", "Reading", "Min"],
                                  title='RPM')
 
     discrete_table = formatting.Table(["Sensor", "Status", "Reading"],
@@ -36,37 +36,26 @@ def cli(env, identifier, discrete):
             temperature_table.add_row([sensor.get('sensorId'),
                                        sensor.get('status'),
                                        sensor.get('sensorReading'),
-                                       sensor.get('lowerCritical'),
-                                       sensor.get('lowerNonCritical'),
                                        sensor.get('upperNonCritical'),
                                        sensor.get('upperCritical')])
 
-        if sensor.get('sensorUnits') == 'Volts':
+        if sensor.get('sensorUnits') == 'volts':
             volts_table.add_row([sensor.get('sensorId'),
                                  sensor.get('status'),
                                  sensor.get('sensorReading'),
-                                 sensor.get('lowerCritical'),
                                  sensor.get('lowerNonCritical'),
-                                 sensor.get('upperNonCritical'),
-                                 sensor.get('upperCritical')])
+                                 sensor.get('lowerCritical')])
 
         if sensor.get('sensorUnits') == 'Watts':
             watts_table.add_row([sensor.get('sensorId'),
                                  sensor.get('status'),
-                                 sensor.get('sensorReading'),
-                                 sensor.get('lowerCritical'),
-                                 sensor.get('lowerNonCritical'),
-                                 sensor.get('upperNonCritical'),
-                                 sensor.get('upperCritical')])
+                                 sensor.get('sensorReading')])
 
         if sensor.get('sensorUnits') == 'RPM':
             rpm_table.add_row([sensor.get('sensorId'),
                                sensor.get('status'),
                                sensor.get('sensorReading'),
-                               sensor.get('lowerCritical'),
-                               sensor.get('lowerNonCritical'),
-                               sensor.get('upperNonCritical'),
-                               sensor.get('upperCritical')])
+                               sensor.get('lowerCritical')])
 
         if sensor.get('sensorUnits') == 'discrete':
             discrete_table.add_row([sensor.get('sensorId'),
diff --git a/SoftLayer/CLI/order/place.py b/SoftLayer/CLI/order/place.py
index 351b9678..eeb9ad2e 100644
--- a/SoftLayer/CLI/order/place.py
+++ b/SoftLayer/CLI/order/place.py
@@ -12,8 +12,9 @@
 from SoftLayer.managers import NetworkManager
 from SoftLayer.managers import ordering
 
-
-COLUMNS = ['keyName', 'description', 'cost']
+COLUMNS = ['keyName',
+           'description',
+           'cost', ]
 
 
 @click.command(cls=SLCommand)
@@ -21,11 +22,17 @@
 @click.argument('location')
 @click.option('--preset',
               help="The order preset (if required by the package)")
-@click.option('--verify', is_flag=True,
+@click.option('--verify',
+              is_flag=True,
               help="Flag denoting whether or not to only verify the order, not place it")
-@click.option('--quantity', type=int, default=1,
+@click.option('--quantity',
+              type=int,
+              default=1,
               help="The quantity of the item being ordered")
-@click.option('--billing', type=click.Choice(['hourly', 'monthly']), default='hourly', show_default=True,
+@click.option('--billing',
+              type=click.Choice(['hourly', 'monthly']),
+              default='hourly',
+              show_default=True,
               help="Billing rate")
 @click.option('--complex-type',
               help=("The complex type of the order. Starts with 'SoftLayer_Container_Product_Order'."))
@@ -61,12 +68,8 @@ def cli(env, package_keyname, location, preset, verify, billing, complex_type,
     manager = ordering.OrderingManager(env.client)
     network = NetworkManager(env.client)
 
-    # Check if this location is going to be shutdown soon.
     pods = network.get_closed_pods()
-    location_dc = network.get_datacenter_by_keyname(location)
-    for pod in pods:
-        if location_dc.get('name') in pod.get('name'):
-            click.secho('Warning: Closed soon: {}'.format(pod.get('name')), fg='yellow')
+    closure = []
 
     if extras:
         try:
@@ -93,6 +96,9 @@ def cli(env, package_keyname, location, preset, verify, billing, complex_type,
             ])
 
     else:
+        for pod in pods:
+            closure.append(pod['name'])
+        click.secho(click.style('Warning: Closed soon: %s' % (', '.join(closure)), fg='yellow'))
         if not (env.skip_confirmations or formatting.confirm(
                 "This action will incur charges on your account. Continue?")):
             raise exceptions.CLIAbort("Aborting order.")
diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py
index 892d2081..10f82273 100644
--- a/SoftLayer/CLI/routes.py
+++ b/SoftLayer/CLI/routes.py
@@ -125,7 +125,6 @@
     ('block:volume-limits', 'SoftLayer.CLI.block.limit:cli'),
     ('block:volume-refresh', 'SoftLayer.CLI.block.refresh:cli'),
     ('block:volume-convert', 'SoftLayer.CLI.block.convert:cli'),
-    ('block:volume-options', 'SoftLayer.CLI.block.options:cli'),
     ('block:volume-set-note', 'SoftLayer.CLI.block.set_note:cli'),
     ('block:object-list', 'SoftLayer.CLI.block.object_list:cli'),
     ('block:object-storage-detail', 'SoftLayer.CLI.block.object_storage_detail:cli'),
@@ -175,7 +174,6 @@
     ('file:volume-limits', 'SoftLayer.CLI.file.limit:cli'),
     ('file:volume-refresh', 'SoftLayer.CLI.file.refresh:cli'),
     ('file:volume-convert', 'SoftLayer.CLI.file.convert:cli'),
-    ('file:volume-options', 'SoftLayer.CLI.file.options:cli'),
     ('file:volume-set-note', 'SoftLayer.CLI.file.set_note:cli'),
 
     ('firewall', 'SoftLayer.CLI.firewall'),
@@ -212,6 +210,7 @@
     ('ipsec:translation-remove', 'SoftLayer.CLI.vpn.ipsec.translation.remove:cli'),
     ('ipsec:translation-update', 'SoftLayer.CLI.vpn.ipsec.translation.update:cli'),
     ('ipsec:update', 'SoftLayer.CLI.vpn.ipsec.update:cli'),
+    ('ipsec:order', 'SoftLayer.CLI.vpn.ipsec.order:cli'),
 
     ('loadbal', 'SoftLayer.CLI.loadbal'),
     ('loadbal:detail', 'SoftLayer.CLI.loadbal.detail:cli'),
diff --git a/SoftLayer/CLI/virt/cancel.py b/SoftLayer/CLI/virt/cancel.py
index db1bbfc4..4d394554 100644
--- a/SoftLayer/CLI/virt/cancel.py
+++ b/SoftLayer/CLI/virt/cancel.py
@@ -21,7 +21,4 @@ def cli(env, identifier):
     if not (env.skip_confirmations or formatting.no_going_back(vs_id)):
         raise exceptions.CLIAbort('Aborted')
 
-    virtual_server = vsi.cancel_instance(vs_id)
-
-    if virtual_server:
-        env.fout("The virtual server instance: {} was cancelled.".format(vs_id))
+    vsi.cancel_instance(vs_id)
diff --git a/SoftLayer/CLI/virt/create.py b/SoftLayer/CLI/virt/create.py
index 3a581a5b..8f6a8f64 100644
--- a/SoftLayer/CLI/virt/create.py
+++ b/SoftLayer/CLI/virt/create.py
@@ -221,11 +221,13 @@ def cli(env, **args):
     network = SoftLayer.NetworkManager(env.client)
 
     pods = network.get_closed_pods()
+    closure = []
 
     if do_create:
         for pod in pods:
             if args.get('datacenter') in str(pod['name']):
-                click.secho('Warning: Closed soon: {}'.format(pod['name']), fg='yellow')
+                closure.append(pod['name'])
+        click.secho(click.style('Warning: Closed soon: %s' % (', '.join(closure)), fg='yellow'))
         if not (env.skip_confirmations or formatting.confirm(
                 "This action will incur charges on your account. Continue?")):
             raise exceptions.CLIAbort('Aborting virtual server order.')
diff --git a/SoftLayer/CLI/vpn/ipsec/order.py b/SoftLayer/CLI/vpn/ipsec/order.py
new file mode 100644
index 00000000..2ca6413e
--- /dev/null
+++ b/SoftLayer/CLI/vpn/ipsec/order.py
@@ -0,0 +1,34 @@
+"""Order a IPSec VPN tunnel."""
+# :licenses: 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(cls=SoftLayer.CLI.command.SLCommand, )
+@click.option('--datacenter', '-d', required=True, prompt=True, help="Datacenter shortname")
+@environment.pass_env
+def cli(env, datacenter):
+    """Order/create a IPSec VPN tunnel instance."""
+
+    ipsec_manager = SoftLayer.IPSECManager(env.client)
+
+    if not (env.skip_confirmations or formatting.confirm(
+            "This action will incur charges on your account. Continue?")):
+        raise exceptions.CLIAbort('Aborting ipsec order.')
+
+    result = ipsec_manager.order(datacenter, ['IPSEC_STANDARD'])
+
+    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']])
+    table.add_row(['Name', result['placedOrder']['items'][0]['description']])
+
+    env.fout(table)
diff --git a/SoftLayer/fixtures/SoftLayer_Hardware.py b/SoftLayer/fixtures/SoftLayer_Hardware.py
index f8164453..3c74dc43 100644
--- a/SoftLayer/fixtures/SoftLayer_Hardware.py
+++ b/SoftLayer/fixtures/SoftLayer_Hardware.py
@@ -62,8 +62,6 @@
 
 getSensorData = [
     {
-        "lowerCritical": "5.000",
-        "lowerNonCritical": "10.000",
         "sensorId": "Ambient 1 Temperature",
         "sensorReading": "25.000",
         "sensorUnits": "degrees C",
@@ -74,13 +72,10 @@
     },
     {
         "lowerCritical": "3500.000",
-        "lowerNonCritical": "3700.000",
         "sensorId": "Fan 1 Tach",
         "sensorReading": "6580.000",
         "sensorUnits": "RPM",
-        "status": "ok",
-        "upperCritical": "25400.000",
-        "upperNonCritical": "25300.000",
+        "status": "ok"
     }, {
         "sensorId": "IPMI Watchdog",
         "sensorReading": "0x0",
@@ -91,16 +86,4 @@
         "sensorReading": "70.000",
         "sensorUnits": "Watts",
         "status": "ok"
-    },
-    {
-        "lowerCritical": "10.536",
-        "lowerNonCritical": "10.780",
-        "lowerNonRecoverable": "10.170",
-        "sensorId": "12V",
-        "sensorReading": "12.305",
-        "sensorUnits": "Volts",
-        "status": "ok",
-        "upperCritical": "13.281",
-        "upperNonCritical": "12.915",
-        "upperNonRecoverable": "13.403"
     }]
diff --git a/SoftLayer/fixtures/SoftLayer_Location.py b/SoftLayer/fixtures/SoftLayer_Location.py
index bb4dcb97..d770d4d8 100644
--- a/SoftLayer/fixtures/SoftLayer_Location.py
+++ b/SoftLayer/fixtures/SoftLayer_Location.py
@@ -1,1 +1,12 @@
-getDatacenters = [{'id': 1854895, 'longName': 'dallas 13', 'name': 'dal13', 'regions': [{'keyname': 'DALLAS13'}]}]
+getDataCenters = [
+    {
+        "id": 358694,
+        "longName": "London 2",
+        "name": "lon02"
+    },
+    {
+        "id": 168642,
+        "longName": "San Jose 1",
+        "name": "sjc01"
+    }]
+getDatacenters = [{'id': 1854895, 'name': 'dal13', 'regions': [{'keyname': 'DALLAS13'}]}]
diff --git a/SoftLayer/fixtures/SoftLayer_Product_Order.py b/SoftLayer/fixtures/SoftLayer_Product_Order.py
index b0d67d86..b5d2dada 100644
--- a/SoftLayer/fixtures/SoftLayer_Product_Order.py
+++ b/SoftLayer/fixtures/SoftLayer_Product_Order.py
@@ -303,3 +303,21 @@
                            "id": 1071,
                            "keyName": "PUBLIC_NETWORK_VLAN"}}
                    ]}
+
+ipsec_placeOrder = {
+    "orderDate": "2022-07-14T16:09:08-06:00",
+    "orderId": 123456,
+    "placedOrder": {
+        "items": [
+            {
+                "categoryCode": "network_tunnel",
+                "description": "IPSEC - Standard",
+                "id": 931479898,
+                "itemId": 1092,
+                "itemPriceId": "2048",
+
+            }
+        ]
+
+    }
+}
diff --git a/SoftLayer/fixtures/SoftLayer_Product_Package.py b/SoftLayer/fixtures/SoftLayer_Product_Package.py
index d2a93d89..8ca1c408 100644
--- a/SoftLayer/fixtures/SoftLayer_Product_Package.py
+++ b/SoftLayer/fixtures/SoftLayer_Product_Package.py
@@ -2171,3 +2171,48 @@
     }]
 }
 ]
+
+getAllObjectsIPSEC = [{
+    "firstOrderStepId": 1,
+    "id": 0,
+    "isActive": 1,
+    "keyName": "ADDITIONAL_PRODUCTS",
+    "name": "Additional Products"}]
+
+getItems_IPSEC = [{
+    "description": "IPSEC - Standard",
+    "id": 1092,
+    "keyName": "IPSEC_STANDARD",
+    "categories": [
+        {
+            "categoryCode": "network_tunnel",
+            "id": 117,
+            "name": "Network Tunnel",
+            "quantityLimit": 0,
+        },
+        {
+            "categoryCode": "one_time_charge",
+            "id": 33,
+            "name": "One Time Charge",
+            "quantityLimit": 0,
+        }
+    ],
+    "itemCategory": {
+        "categoryCode": "network_tunnel",
+        "id": 117,
+        "name": "Network Tunnel",
+        "quantityLimit": 0,
+    },
+    "prices": [
+        {
+            "id": 51379,
+            "itemId": 1092,
+            "laborFee": "0",
+            "locationGroupId": 503,
+            "oneTimeFee": "0",
+            "recurringFee": "102",
+            "setupFee": "0",
+            "sort": 0,
+        }
+    ]
+}]
diff --git a/SoftLayer/managers/ipsec.py b/SoftLayer/managers/ipsec.py
index 29317516..1043b2f1 100644
--- a/SoftLayer/managers/ipsec.py
+++ b/SoftLayer/managers/ipsec.py
@@ -7,6 +7,7 @@
 """
 
 from SoftLayer.exceptions import SoftLayerAPIError
+from SoftLayer.managers import ordering
 from SoftLayer import utils
 
 
@@ -284,3 +285,17 @@ def update_tunnel_context(self, context_id, friendly_name=None,
         if phase2_key_ttl is not None:
             context['phaseTwoKeylife'] = phase2_key_ttl
         return self.context.editObject(context, id=context_id)
+
+    def order(self, datacenter, item_package):
+        """Create a ipsec.
+
+        :param string datacenter: the datacenter shortname
+        :param string[] item_package: items array
+        """
+        complex_type = 'SoftLayer_Container_Product_Order_Network_Tunnel_Ipsec'
+        ordering_manager = ordering.OrderingManager(self.client)
+        return ordering_manager.place_order(package_keyname='ADDITIONAL_PRODUCTS',
+                                            location=datacenter,
+                                            item_keynames=item_package,
+                                            complex_type=complex_type,
+                                            hourly=False)
diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py
index ae4cc829..2480974a 100644
--- a/SoftLayer/managers/network.py
+++ b/SoftLayer/managers/network.py
@@ -851,18 +851,3 @@ def get_datacenter(self, _filter=None, datacenter=None):
             _filter = {"name": {"operation": datacenter}}
 
         return self.client.call('SoftLayer_Location', 'getDatacenters', filter=_filter, limit=1)
-
-    def get_datacenter_by_keyname(self, keyname=None):
-        """Calls SoftLayer_Location::getDatacenters()
-
-        returns datacenter list.
-        """
-        mask = "mask[id,longName,name,regions[keyname,description]]"
-        _filter = {}
-        if keyname:
-            _filter = {"regions": {"keyname": {"operation": keyname}}}
-
-        result = self.client.call('SoftLayer_Location', 'getDatacenters', filter=_filter, limit=1, mask=mask)
-        if len(result) >= 1:
-            return result[0]
-        return {}
diff --git a/SoftLayer/managers/ordering.py b/SoftLayer/managers/ordering.py
index 26bbed43..92b39102 100644
--- a/SoftLayer/managers/ordering.py
+++ b/SoftLayer/managers/ordering.py
@@ -6,6 +6,7 @@
     :license: MIT, see LICENSE for more details.
 """
 
+
 from re import match
 
 from SoftLayer import exceptions
@@ -716,21 +717,3 @@ def resolve_location_name(self, location_key):
             if location.get('regions', default_regions)[index_first].get('keyname') == location_key:
                 return location_name
         raise exceptions.SoftLayerError("Location {} does not exist".format(location_key))
-
-    def get_items(self, package_id, storage_filter=None):
-        """"Returns the items .
-
-
-        :param int package_id: The package for which to get the items.
-        :param dict storage_filter: object filter.
-        """
-
-        return self.client.call('SoftLayer_Product_Package', 'getItems', filter=storage_filter,
-                                id=package_id)
-
-    def get_regions(self, package_id):
-        """returns the all regions.
-
-        :param int package_id: The package for which to get the items.
-        """
-        return self.client.call('SoftLayer_Product_Package', 'getRegions', id=package_id)
diff --git a/docs/cli/block.rst b/docs/cli/block.rst
index fe58d90b..9078795c 100644
--- a/docs/cli/block.rst
+++ b/docs/cli/block.rst
@@ -83,10 +83,6 @@ Block Commands
     :prog: block volume-count
     :show-nested:
 
-.. click:: SoftLayer.CLI.block.options:cli
-    :prog: block volume-options
-    :show-nested:
-
 .. click:: SoftLayer.CLI.block.detail:cli
     :prog: block volume-detail
     :show-nested:
diff --git a/docs/cli/file.rst b/docs/cli/file.rst
index 55f1b085..eca4f5b3 100644
--- a/docs/cli/file.rst
+++ b/docs/cli/file.rst
@@ -123,10 +123,6 @@ File Commands
     :prog: file volume-set-note
     :show-nested:
 
-.. click:: SoftLayer.CLI.file.options:cli
-    :prog: file volume-options
-    :show-nested:
-
 .. click:: SoftLayer.CLI.file.replication.disaster_recovery_failover:cli
     :prog: file disaster-recovery-failover
     :show-nested:
diff --git a/docs/cli/ipsec.rst b/docs/cli/ipsec.rst
index cc1ed5b1..8bfb9905 100644
--- a/docs/cli/ipsec.rst
+++ b/docs/cli/ipsec.rst
@@ -272,3 +272,7 @@ The following is an example of updating an existing address translation entry.
 
     $ slcli ipsec translation-update 445 --translation-id 15924 --static-ip 10.1.249.86 --remote-ip 50.100.0.8 --note 'new email server'
     Updated translation #15924
+
+.. click:: SoftLayer.CLI.vpn.ipsec.order:cli
+    :prog: ipsec order
+    :show-nested:
\ No newline at end of file


Test patch:
diff --git a/tests/CLI/helper_tests.py b/tests/CLI/helper_tests.py
index 1c8c2d91..cecb3293 100644
--- a/tests/CLI/helper_tests.py
+++ b/tests/CLI/helper_tests.py
@@ -396,12 +396,6 @@ def test_format_output_table_invalid_sort(self):
             formatting.format_output, t, 'table',
         )
 
-    def test_format_raw_table(self):
-        test_table = formatting.Table(['col1', 'col2'])
-        test_table.add_row(['row1', 'row2'])
-        pretty_table = formatting.format_output(test_table, 'raw')
-        self.assertIsNone(pretty_table.box)
-
 
 class TestTemplateArgs(testing.TestCase):
 
@@ -484,13 +478,3 @@ def test_format_api_list_with_none_value(self):
 
         self.assertIsInstance(result, formatting.Table)
         self.assertEqual(result.columns, ['key'])
-
-    def test_format_api_list_with_empty_array(self):
-        result = formatting.iter_to_table([{'id': 130224450, 'activeTickets': []}])
-        self.assertIsInstance(result, formatting.Table)
-        self.assertIn('id', result.columns)
-        self.assertIn('activeTickets', result.columns)
-        formatted = formatting.format_output(result, "table")
-        # No good ways to test whats actually in a Rich.Table without going through the hassel of
-        # printing it out. As long as this didn't throw and exception it should be fine.
-        self.assertEqual(formatted.row_count, 1)
diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py
index 5b082b70..0db01ac0 100644
--- a/tests/CLI/modules/block_tests.py
+++ b/tests/CLI/modules/block_tests.py
@@ -792,11 +792,6 @@ def test_dep_dupe_convert(self):
 
         self.assert_no_fail(result)
 
-    def test_volume_options(self):
-        result = self.run_command(['block', 'volume-options'])
-
-        self.assert_no_fail(result)
-
     @mock.patch('SoftLayer.BlockStorageManager.volume_set_note')
     def test_volume_set_note(self, set_note):
         set_note.return_value = True
diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py
index 6943399b..6bd56bd0 100644
--- a/tests/CLI/modules/file_tests.py
+++ b/tests/CLI/modules/file_tests.py
@@ -798,7 +798,3 @@ def test_snapshot_get_notification_status(self, status):
             result = self.run_command(['file', 'snapshot-get-notification-status', '999'])
             self.assert_no_fail(result)
             self.assertIn(expect, result.output)
-
-    def test_volume_options(self):
-        result = self.run_command(['file', 'volume-options'])
-        self.assert_no_fail(result)
diff --git a/tests/CLI/modules/ipsec_tests.py b/tests/CLI/modules/ipsec_tests.py
index 777df8b9..5a7a6589 100644
--- a/tests/CLI/modules/ipsec_tests.py
+++ b/tests/CLI/modules/ipsec_tests.py
@@ -7,8 +7,11 @@
 
 import json
 
+
 from SoftLayer.CLI.exceptions import ArgumentError
 from SoftLayer.CLI.exceptions import CLIHalt
+from SoftLayer.fixtures import SoftLayer_Product_Order
+from SoftLayer.fixtures import SoftLayer_Product_Package
 from SoftLayer import testing
 from SoftLayer import utils
 
@@ -508,3 +511,12 @@ def test_ipsec_translation_update(self):
                                        'internalIpAddress': '10.50.0.1',
                                        'customerIpAddress': '50.50.0.1',
                                        'notes': 'lost'},))
+
+    def test_ipsec_order(self):
+        _mock = self.set_mock('SoftLayer_Product_Package', 'getItems')
+        _mock.return_value = SoftLayer_Product_Package.getItems_IPSEC
+
+        order_mock = self.set_mock('SoftLayer_Product_Order', 'placeOrder')
+        order_mock.return_value = SoftLayer_Product_Order.ipsec_placeOrder
+        result = self.run_command(['ipsec', 'order', '-d', 'dal13'])
+        self.assert_no_fail(result)
diff --git a/tests/CLI/modules/order_tests.py b/tests/CLI/modules/order_tests.py
index 246aa920..c1541594 100644
--- a/tests/CLI/modules/order_tests.py
+++ b/tests/CLI/modules/order_tests.py
@@ -7,8 +7,6 @@
 import sys
 import tempfile
 
-from unittest import mock as mock
-
 from SoftLayer.CLI import exceptions
 from SoftLayer import testing
 
@@ -143,12 +141,10 @@ def test_place(self):
 
         self.assert_no_fail(result)
         self.assert_called_with('SoftLayer_Product_Order', 'placeOrder')
-        self.assertNotIn('Warning: Closed soon: dal13', result.output)
+        self.assertIn('Warning: Closed soon: ams01.pod01, wdc07.pod01, TEST00.pod2', result.output)
         self.assertIn('"status": "APPROVED"', result.output)
 
-    @mock.patch('SoftLayer.managers.network.NetworkManager.get_datacenter_by_keyname')
-    def test_place_with_quantity(self, keyname_mock):
-        keyname_mock.return_value = {"name": "ams01"}
+    def test_place_with_quantity(self):
         order_date = '2017-04-04 07:39:20'
         order = {'orderId': 1234, 'orderDate': order_date, 'placedOrder': {'status': 'APPROVED'}}
         verify_mock = self.set_mock('SoftLayer_Product_Order', 'verifyOrder')
@@ -159,12 +155,12 @@ def test_place_with_quantity(self, keyname_mock):
         place_mock.return_value = order
         items_mock.return_value = self._get_order_items()
 
-        result = self.run_command(['-y', 'order', 'place', '--quantity=2', 'package', 'AMSTERDAM', 'ITEM1',
+        result = self.run_command(['-y', 'order', 'place', '--quantity=2', 'package', 'DALLAS13', 'ITEM1',
                                    '--complex-type', 'SoftLayer_Container_Product_Order_Thing'])
 
         self.assert_no_fail(result)
         self.assert_called_with('SoftLayer_Product_Order', 'placeOrder')
-        self.assertIn('Warning: Closed soon: ams01.pod01', result.output)
+        self.assertIn('Warning: Closed soon: ams01.pod01, wdc07.pod01, TEST00.pod2', result.output)
         self.assertIn('"status": "APPROVED"', result.output)
 
     def test_place_extras_parameter_fail(self):
diff --git a/tests/CLI/modules/server_tests.py b/tests/CLI/modules/server_tests.py
index cc30c70e..9f8653c0 100644
--- a/tests/CLI/modules/server_tests.py
+++ b/tests/CLI/modules/server_tests.py
@@ -401,17 +401,6 @@ def test_create_server(self, order_mock):
         self.assertIn('Warning: Closed soon: TEST00.pod2', result.output)
         self.assertIn('"id": 98765', result.output)
 
-        result = self.run_command(['--really', 'server', 'create',
-                                   '--size=S1270_8GB_2X1TBSATA_NORAID',
-                                   '--hostname=test',
-                                   '--domain=example.com',
-                                   '--datacenter=mex01',
-                                   '--os=OS_UBUNTU_14_04_LTS_TRUSTY_TAHR_64_BIT',
-                                   ])
-
-        self.assert_no_fail(result)
-        self.assertNotIn('Warning: Closed soon: mex01', result.output)
-
     @mock.patch('SoftLayer.CLI.template.export_to_template')
     def test_create_server_with_export(self, export_mock):
 
@@ -1026,15 +1015,3 @@ def test_sensor_discrete(self):
     def test_monitoring(self):
         result = self.run_command(['hardware', 'monitoring', '100'])
         self.assert_no_fail(result)
-
-    @mock.patch('SoftLayer.CLI.formatting.confirm')
-    def test_check_for_closing(self, confirm_mock):
-        confirm_mock.return_value = True
-        result = self.run_command(['vs', 'create', '--hostname', 'TEST', '--domain', 'TESTING',
-                                   '--flavor', 'B1_2X8X25', '--datacenter', 'ams01', '--os', 'UBUNTU_LATEST'])
-        self.assert_no_fail(result)
-        self.assertIn('Warning: Closed soon: ams01', result.output)
-        result = self.run_command(['vs', 'create', '--hostname', 'TEST', '--domain', 'TESTING',
-                                   '--flavor', 'B1_2X8X25', '--datacenter', 'mex01', '--os', 'UBUNTU_LATEST'])
-        self.assert_no_fail(result)
-        self.assertNotIn('Warning: Closed soon: mex01', result.output)
diff --git a/tests/CLI/modules/vs/vs_create_tests.py b/tests/CLI/modules/vs/vs_create_tests.py
index 468bc533..efcb8cbc 100644
--- a/tests/CLI/modules/vs/vs_create_tests.py
+++ b/tests/CLI/modules/vs/vs_create_tests.py
@@ -722,15 +722,3 @@ def test_create_with_userdata(self, confirm_mock):
         api_call = self.calls('SoftLayer_Product_Order', 'placeOrder')
         # Doing this because the placeOrder args are huge and mostly not needed to test
         self.assertEqual(api_call[0].args[0]['virtualGuests'], expected_guest)
-
-    @mock.patch('SoftLayer.CLI.formatting.confirm')
-    def test_check_for_closing(self, confirm_mock):
-        confirm_mock.return_value = True
-        result = self.run_command(['vs', 'create', '--hostname', 'TEST', '--domain', 'TESTING',
-                                   '--flavor', 'B1_2X8X25', '--datacenter', 'ams01', '--os', 'UBUNTU_LATEST'])
-        self.assert_no_fail(result)
-        self.assertIn('Warning: Closed soon: ams01', result.output)
-        result = self.run_command(['vs', 'create', '--hostname', 'TEST', '--domain', 'TESTING',
-                                   '--flavor', 'B1_2X8X25', '--datacenter', 'mex01', '--os', 'UBUNTU_LATEST'])
-        self.assert_no_fail(result)
-        self.assertNotIn('Warning: Closed soon: mex01', result.output)
diff --git a/tests/managers/ipsec_tests.py b/tests/managers/ipsec_tests.py
index f88e33ed..1d86f20d 100644
--- a/tests/managers/ipsec_tests.py
+++ b/tests/managers/ipsec_tests.py
@@ -8,6 +8,9 @@
 
 import SoftLayer
 from SoftLayer.exceptions import SoftLayerAPIError
+from SoftLayer.fixtures import SoftLayer_Product_Order
+from SoftLayer.fixtures import SoftLayer_Product_Package
+
 from SoftLayer import testing
 
 
@@ -299,3 +302,20 @@ def test_update_tunnel_context(self):
                                        'phaseTwoKeylife': 240,
                                        'phaseTwoPerfectForwardSecrecy': 1},),
                                 identifier=445)
+
+    def test_order(self):
+        _mock = self.set_mock('SoftLayer_Product_Package', 'getItems')
+        _mock.return_value = SoftLayer_Product_Package.getItems_IPSEC
+
+        _mock = self.set_mock('SoftLayer_Product_Order', 'placeOrder')
+        _mock.return_value = SoftLayer_Product_Order.ipsec_placeOrder
+        result = self.ipsec.order('dal13', ['IPSEC_STANDARD'])
+        order = {
+            'orderDate': '2022-07-14T16:09:08-06:00',
+            'orderId': 123456, 'placedOrder': {'items': [
+                {'categoryCode': 'network_tunnel',
+                 'description': 'IPSEC - Standard',
+                 'id': 931479898,
+                 'itemId': 1092,
+                 'itemPriceId': '2048'}]}}
+        self.assertEqual(result, order)
diff --git a/tests/managers/network_tests.py b/tests/managers/network_tests.py
index 04c2d8d6..81a91faf 100644
--- a/tests/managers/network_tests.py
+++ b/tests/managers/network_tests.py
@@ -637,19 +637,3 @@ def test_route(self):
     def test_get_all_datacenter(self):
         self.network.get_datacenter()
         self.assert_called_with('SoftLayer_Location', 'getDatacenters')
-        self.network.get_datacenter(datacenter="dal11")
-        expected_filter = {"name": {"operation": "dal11"}}
-        self.assert_called_with('SoftLayer_Location', 'getDatacenters', filter=expected_filter)
-
-    def test_get_datacenter_by_keyname(self):
-        # normal operation
-        result = self.network.get_datacenter_by_keyname("TEST01")
-        expected_filter = {"regions": {"keyname": {"operation": "TEST01"}}}
-        self.assert_called_with('SoftLayer_Location', 'getDatacenters', filter=expected_filter)
-        self.assertEqual(result.get('name'), 'dal13')
-
-        # an "empty" result
-        SoftLayer_Location = self.set_mock('SoftLayer_Location', 'getDatacenters')
-        SoftLayer_Location.return_value = []
-        result = self.network.get_datacenter_by_keyname("TEST01")
-        self.assertEqual(result, {})
diff --git a/tests/managers/ordering_tests.py b/tests/managers/ordering_tests.py
index 063dbcdd..b25c4249 100644
--- a/tests/managers/ordering_tests.py
+++ b/tests/managers/ordering_tests.py
@@ -744,7 +744,7 @@ def test_get_item_capacity_core(self):
                 "capacity": "1",
                 "id": 10201,
                 "keyName": "GUEST_CORE_1_DEDICATED",
-            }]
+        }]
 
         item_capacity = self.ordering.get_item_capacity(items, ['GUEST_CORE_1_DEDICATED', 'OS_RHEL_7_X_LAMP_64_BIT'])
 
@@ -761,7 +761,7 @@ def test_get_item_capacity_storage(self):
                 "capacity": "1",
                 "id": 10201,
                 "keyName": "READHEAVY_TIER",
-            }]
+        }]
 
         item_capacity = self.ordering.get_item_capacity(items, ['READHEAVY_TIER', 'STORAGE_SPACE_FOR_2_IOPS_PER_GB'])
 
@@ -779,7 +779,7 @@ def test_get_item_capacity_intel(self):
                 "capacity": "1",
                 "id": 10201,
                 "keyName": "GUEST_CORE_1_DEDICATED",
-            }]
+        }]
 
         item_capacity = self.ordering.get_item_capacity(items, ['INTEL_XEON_2690_2_60', 'BANDWIDTH_20000_GB'])
 
@@ -893,11 +893,3 @@ def test_issues1425_nonzeroterm(self):
         # Test None-existing price for term
         price_id = self.ordering.get_item_price_id("8", [price2, price1], 37)
         self.assertEqual(None, price_id)
-
-    def test_get_items(self):
-        self.ordering.get_items(123)
-        self.assert_called_with('SoftLayer_Product_Package', 'getItems')
-
-    def test_get_regions(self):
-        self.ordering.get_regions(123)
-        self.assert_called_with('SoftLayer_Product_Package', 'getRegions')