1"""
2    SoftLayer.tests.managers.dedicated_host_tests
3    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5    :license: MIT, see LICENSE for more details.
6"""
7from unittest import mock as mock
8
9import SoftLayer
10from SoftLayer import exceptions
11from SoftLayer import fixtures
12from SoftLayer import testing
13
14
15class DedicatedHostTests(testing.TestCase):
16    def set_up(self):
17        self.dedicated_host = SoftLayer.DedicatedHostManager(self.client)
18
19    def test_list_instances(self):
20        results = self.dedicated_host.list_instances()
21
22        self.assertEqual(results, fixtures.SoftLayer_Account.getDedicatedHosts)
23        self.assert_called_with('SoftLayer_Account', 'getDedicatedHosts')
24
25    def test_list_instances_with_filters(self):
26        results = self.dedicated_host.list_instances(
27            tags=['tag1', 'tag2'],
28            cpus=2,
29            memory=1,
30            hostname='hostname',
31            datacenter='dal05',
32            disk=1
33        )
34        self.assertEqual(results, fixtures.SoftLayer_Account.getDedicatedHosts)
35
36    def test_get_host(self):
37
38        self.dedicated_host.host = mock.Mock()
39        self.dedicated_host.host.getObject.return_value = 'test'
40
41        self.dedicated_host.get_host(12345)
42
43        mask = ('''
44                id,
45                name,
46                cpuCount,
47                memoryCapacity,
48                diskCapacity,
49                createDate,
50                modifyDate,
51                backendRouter[
52                    id,
53                    hostname,
54                    domain
55                ],
56                billingItem[
57                    id,
58                    nextInvoiceTotalRecurringAmount,
59                    children[
60                        categoryCode,
61                        nextInvoiceTotalRecurringAmount
62                    ],
63                    orderItem[
64                        id,
65                        order.userRecord[
66                            username
67                        ]
68                    ]
69                ],
70                datacenter[
71                    id,
72                    name,
73                    longName
74                ],
75                guests[
76                    id,
77                    hostname,
78                    domain,
79                    uuid
80                ],
81                guestCount
82            ''')
83        self.dedicated_host.host.getObject.assert_called_once_with(id=12345, mask=mask)
84
85    def test_place_order(self):
86        create_dict = self.dedicated_host._generate_create_dict = mock.Mock()
87
88        values = {
89            'hardware': [
90                {
91                    'primaryBackendNetworkComponent': {
92                        'router': {
93                            'id': 12345
94                        }
95                    },
96                    'domain': u'test.com',
97                    'hostname': u'test'
98                }
99            ],
100            'useHourlyPricing': True,
101            'location': 'AMSTERDAM',
102            'packageId': 813,
103            'complexType': 'SoftLayer_Container_Product_Order_Virtual_DedicatedHost',
104            'prices': [
105                {
106                    'id': 12345
107                }
108            ],
109            'quantity': 1
110        }
111        create_dict.return_value = values
112
113        location = 'dal05'
114        hostname = 'test'
115        domain = 'test.com'
116        hourly = True
117        flavor = '56_CORES_X_242_RAM_X_1_4_TB'
118
119        self.dedicated_host.place_order(hostname=hostname,
120                                        domain=domain,
121                                        location=location,
122                                        flavor=flavor,
123                                        hourly=hourly)
124
125        create_dict.assert_called_once_with(hostname=hostname,
126                                            router=None,
127                                            domain=domain,
128                                            datacenter=location,
129                                            flavor=flavor,
130                                            hourly=True)
131
132        self.assert_called_with('SoftLayer_Product_Order',
133                                'placeOrder',
134                                args=(values,))
135
136    def test_place_order_with_gpu(self):
137        create_dict = self.dedicated_host._generate_create_dict = mock.Mock()
138
139        values = {
140            'hardware': [
141                {
142                    'primaryBackendNetworkComponent': {
143                        'router': {
144                            'id': 12345
145                        }
146                    },
147                    'domain': u'test.com',
148                    'hostname': u'test'
149                }
150            ],
151            'useHourlyPricing': True,
152            'location': 'AMSTERDAM',
153            'packageId': 813,
154            'complexType': 'SoftLayer_Container_Product_Order_Virtual_DedicatedHost',
155            'prices': [
156                {
157                    'id': 12345
158                }
159            ],
160            'quantity': 1
161        }
162        create_dict.return_value = values
163
164        location = 'dal05'
165        hostname = 'test'
166        domain = 'test.com'
167        hourly = True
168        flavor = '56_CORES_X_484_RAM_X_1_5_TB_X_2_GPU_P100'
169
170        self.dedicated_host.place_order(hostname=hostname,
171                                        domain=domain,
172                                        location=location,
173                                        flavor=flavor,
174                                        hourly=hourly)
175
176        create_dict.assert_called_once_with(hostname=hostname,
177                                            router=None,
178                                            domain=domain,
179                                            datacenter=location,
180                                            flavor=flavor,
181                                            hourly=True)
182
183        self.assert_called_with('SoftLayer_Product_Order',
184                                'placeOrder',
185                                args=(values,))
186
187    def test_verify_order(self):
188        create_dict = self.dedicated_host._generate_create_dict = mock.Mock()
189
190        values = {
191            'hardware': [
192                {
193                    'primaryBackendNetworkComponent': {
194                        'router': {
195                            'id': 12345
196                        }
197                    },
198                    'domain': 'test.com',
199                    'hostname': 'test'
200                }
201            ],
202            'useHourlyPricing': True,
203            'location': 'AMSTERDAM',
204            'packageId': 813,
205            'complexType': 'SoftLayer_Container_Product_Order_Virtual_DedicatedHost',
206            'prices': [
207                {
208                    'id': 12345
209                }
210            ],
211            'quantity': 1
212        }
213        create_dict.return_value = values
214
215        location = 'dal05'
216        hostname = 'test'
217        domain = 'test.com'
218        hourly = True
219        flavor = '56_CORES_X_242_RAM_X_1_4_TB'
220
221        self.dedicated_host.verify_order(hostname=hostname,
222                                         domain=domain,
223                                         location=location,
224                                         flavor=flavor,
225                                         hourly=hourly)
226
227        create_dict.assert_called_once_with(hostname=hostname,
228                                            router=None,
229                                            domain=domain,
230                                            datacenter=location,
231                                            flavor=flavor,
232                                            hourly=True)
233
234        self.assert_called_with('SoftLayer_Product_Order',
235                                'verifyOrder',
236                                args=(values,))
237
238    def test_generate_create_dict_without_router(self):
239        self.dedicated_host._get_package = mock.MagicMock()
240        self.dedicated_host._get_package.return_value = self._get_package()
241        self.dedicated_host._get_backend_router = mock.Mock()
242        self.dedicated_host._get_backend_router.return_value = self \
243            ._get_routers_sample()
244
245        location = 'dal05'
246        hostname = 'test'
247        domain = 'test.com'
248        hourly = True
249        flavor = '56_CORES_X_242_RAM_X_1_4_TB'
250
251        results = self.dedicated_host._generate_create_dict(hostname=hostname,
252                                                            domain=domain,
253                                                            datacenter=location,
254                                                            flavor=flavor,
255                                                            hourly=hourly)
256
257        testResults = {
258            'hardware': [
259                {
260                    'primaryBackendNetworkComponent': {
261                        'router': {
262                            'id': 12345
263                        }
264                    },
265                    'domain': 'test.com',
266                    'hostname': 'test'
267                }
268            ],
269            'useHourlyPricing': True,
270            'location': 'DALLAS05',
271            'packageId': 813,
272            'complexType': 'SoftLayer_Container_Product_Order_Virtual_DedicatedHost',
273            'prices': [
274                {
275                    'id': 12345
276                }
277            ],
278            'quantity': 1
279        }
280
281        self.assertEqual(results, testResults)
282
283    def test_generate_create_dict_with_router(self):
284        self.dedicated_host._get_package = mock.MagicMock()
285        self.dedicated_host._get_package.return_value = self._get_package()
286        self.dedicated_host._get_default_router = mock.Mock()
287        self.dedicated_host._get_default_router.return_value = 12345
288
289        location = 'dal05'
290        router = 12345
291        hostname = 'test'
292        domain = 'test.com'
293        hourly = True
294        flavor = '56_CORES_X_242_RAM_X_1_4_TB'
295
296        results = self.dedicated_host._generate_create_dict(
297            hostname=hostname,
298            router=router,
299            domain=domain,
300            datacenter=location,
301            flavor=flavor,
302            hourly=hourly)
303
304        testResults = {
305            'hardware': [
306                {
307                    'primaryBackendNetworkComponent': {
308                        'router': {
309                            'id': 12345
310                        }
311                    },
312                    'domain': 'test.com',
313                    'hostname': 'test'
314                }
315            ],
316            'useHourlyPricing': True,
317            'location': 'DALLAS05',
318            'packageId': 813,
319            'complexType':
320                'SoftLayer_Container_Product_Order_Virtual_DedicatedHost',
321            'prices': [
322                {
323                    'id': 12345
324                }
325            ],
326            'quantity': 1
327        }
328
329        self.assertEqual(results, testResults)
330
331    def test_get_package(self):
332        mask = '''
333        items[
334            id,
335            description,
336            prices,
337            capacity,
338            keyName,
339            itemCategory[categoryCode],
340            bundleItems[capacity,keyName,categories[categoryCode],hardwareGenericComponentModel[id,
341            hardwareComponentType[keyName]]]
342        ],
343        regions[location[location[priceGroups]]]
344        '''
345        self.dedicated_host.ordering_manager = mock.Mock()
346
347        self.dedicated_host.ordering_manager.get_package_by_key.return_value = \
348            "test"
349
350        package = self.dedicated_host._get_package()
351
352        package_keyname = 'DEDICATED_HOST'
353
354        self.assertEqual('test', package)
355        self.dedicated_host.ordering_manager.get_package_by_key. \
356            assert_called_once_with(package_keyname, mask=mask)
357
358    def test_get_package_no_package_found(self):
359        packages = self.set_mock('SoftLayer_Product_Package', 'getAllObjects')
360        packages.return_value = []
361
362        self.assertRaises(exceptions.SoftLayerError, self.dedicated_host._get_package)
363
364    def test_get_location(self):
365        regions = [{
366            "location": {
367                "location": {
368                    "name": "dal05",
369                }
370            }
371        }]
372
373        region = {
374            'location':
375                {
376                    'location': {
377                        'name': 'dal05',
378                    }
379                }
380        }
381
382        testing = self.dedicated_host._get_location(regions, 'dal05')
383
384        self.assertEqual(testing, region)
385
386    def test_get_location_no_location_found(self):
387        regions = [{
388            "location": {
389                "location": {
390                    "name": "dal05",
391                }
392            }
393        }]
394
395        self.assertRaises(exceptions.SoftLayerError,
396                          self.dedicated_host._get_location, regions, 'dal10')
397
398    def test_get_create_options(self):
399        self.dedicated_host._get_package = mock.MagicMock()
400        self.dedicated_host._get_package.return_value = self._get_package()
401
402        results = {
403            'dedicated_host': [{
404                'key': '56_CORES_X_242_RAM_X_1_4_TB',
405                'name': '56 Cores X 242 RAM X 1.2 TB'
406            }],
407            'locations': [
408                {
409                    'key': 'ams01',
410                    'name': 'Amsterdam 1'
411                },
412                {
413                    'key': 'dal05',
414                    'name': 'Dallas 5'
415                }
416            ]
417        }
418
419        self.assertEqual(self.dedicated_host.get_create_options(), results)
420
421    def test_get_price(self):
422        package = self._get_package()
423        item = package['items'][0]
424        price_id = 12345
425
426        self.assertEqual(self.dedicated_host._get_price(item), price_id)
427
428    def test_get_price_no_price_found(self):
429        package = self._get_package()
430        package['items'][0]['prices'][0]['locationGroupId'] = 33
431        item = package['items'][0]
432
433        self.assertRaises(exceptions.SoftLayerError, self.dedicated_host._get_price, item)
434
435    def test_get_item(self):
436        """Returns the item for ordering a dedicated host."""
437        package = self._get_package()
438        flavor = '56_CORES_X_242_RAM_X_1_4_TB'
439
440        item = {
441            'bundleItems': [{
442                'capacity': '1200',
443                'keyName': '1_4_TB_LOCAL_STORAGE_DEDICATED_HOST_CAPACITY',
444                'categories': [{
445                    'categoryCode': 'dedicated_host_disk'
446                }]
447            },
448                {
449                    'capacity': '242',
450                    'keyName': '242_GB_RAM',
451                    'categories': [{
452                        'categoryCode': 'dedicated_host_ram'
453                    }]
454            }],
455            'capacity': '56',
456            'description': '56 Cores X 242 RAM X 1.2 TB',
457            'id': 12345,
458            'itemCategory': {
459                'categoryCode': 'dedicated_virtual_hosts'
460            },
461            'keyName': '56_CORES_X_242_RAM_X_1_4_TB',
462            'prices': [{
463                'hourlyRecurringFee': '3.164',
464                'id': 12345,
465                'itemId': 12345,
466                'recurringFee': '2099',
467            }]
468        }
469
470        self.assertEqual(self.dedicated_host._get_item(package, flavor), item)
471
472    def test_get_item_no_item_found(self):
473        package = self._get_package()
474
475        flavor = '56_CORES_X_242_RAM_X_1_4_TB'
476        package['items'][0]['keyName'] = 'not found'
477
478        self.assertRaises(exceptions.SoftLayerError, self.dedicated_host._get_item, package, flavor)
479
480    def test_get_backend_router(self):
481        location = [
482            {
483                'isAvailable': 1,
484                'locationId': 12345,
485                'packageId': 813
486            }
487        ]
488
489        locId = location[0]['locationId']
490
491        mask = '''
492            id,
493            hostname
494        '''
495
496        host = {
497            'cpuCount': '56',
498            'memoryCapacity': '242',
499            'diskCapacity': '1200',
500            'datacenter': {
501                'id': locId
502            }
503        }
504
505        self.dedicated_host.host = mock.Mock()
506
507        routers = self.dedicated_host.host.getAvailableRouters.return_value = \
508            self._get_routers_sample()
509
510        item = self._get_package()['items'][0]
511
512        routers_test = self.dedicated_host._get_backend_router(location, item)
513
514        self.assertEqual(routers, routers_test)
515        self.dedicated_host.host.getAvailableRouters.assert_called_once_with(host, mask=mask)
516
517    def test_get_backend_router_no_routers_found(self):
518        location = []
519
520        self.dedicated_host.host = mock.Mock()
521
522        routers_test = self.dedicated_host._get_backend_router
523
524        item = self._get_package()['items'][0]
525
526        self.assertRaises(exceptions.SoftLayerError, routers_test, location, item)
527
528    def test_get_default_router(self):
529        routers = self._get_routers_sample()
530
531        router = 12345
532
533        router_test = self.dedicated_host._get_default_router(routers, 'bcr01a.dal05')
534
535        self.assertEqual(router_test, router)
536
537    def test_get_default_router_no_router_found(self):
538        routers = []
539
540        self.assertRaises(exceptions.SoftLayerError,
541                          self.dedicated_host._get_default_router, routers, 'notFound')
542
543    def test_cancel_host(self):
544        result = self.dedicated_host.cancel_host(789)
545
546        self.assertEqual(result, True)
547        self.assert_called_with('SoftLayer_Virtual_DedicatedHost', 'deleteObject', identifier=789)
548
549    def test_cancel_guests(self):
550        vs1 = {'id': 987, 'fullyQualifiedDomainName': 'foobar.example.com'}
551        vs2 = {'id': 654, 'fullyQualifiedDomainName': 'wombat.example.com'}
552        self.dedicated_host.host = mock.Mock()
553        self.dedicated_host.host.getGuests.return_value = [vs1, vs2]
554
555        # Expected result
556        vs_status1 = {'id': 987, 'fqdn': 'foobar.example.com', 'status': 'Cancelled'}
557        vs_status2 = {'id': 654, 'fqdn': 'wombat.example.com', 'status': 'Cancelled'}
558        delete_status = [vs_status1, vs_status2]
559
560        result = self.dedicated_host.cancel_guests(789)
561
562        self.assertEqual(result, delete_status)
563
564    def test_cancel_guests_empty_list(self):
565        self.dedicated_host.host = mock.Mock()
566        self.dedicated_host.host.getGuests.return_value = []
567
568        result = self.dedicated_host.cancel_guests(789)
569
570        self.assertEqual(result, [])
571
572    def test_delete_guest(self):
573        result = self.dedicated_host._delete_guest(123)
574        self.assertEqual(result, 'Cancelled')
575
576        # delete_guest should return the exception message in case it fails
577        error_raised = SoftLayer.SoftLayerAPIError('SL Exception', 'SL message')
578        self.dedicated_host.guest = mock.Mock()
579        self.dedicated_host.guest.deleteObject.side_effect = error_raised
580
581        result = self.dedicated_host._delete_guest(369)
582        self.assertEqual(result, 'Exception: SL message')
583
584    def _get_routers_sample(self):
585        routers = [
586            {
587                'hostname': 'bcr01a.dal05',
588                'id': 12345
589            },
590            {
591                'hostname': 'bcr02a.dal05',
592                'id': 12346
593            },
594            {
595                'hostname': 'bcr03a.dal05',
596                'id': 12347
597            },
598            {
599                'hostname': 'bcr04a.dal05',
600                'id': 12348
601            }
602        ]
603
604        return routers
605
606    def _get_package(self):
607        package = {
608            "items": [
609                {
610                    "capacity": "56",
611                    "description": "56 Cores X 242 RAM X 1.2 TB",
612                    "bundleItems": [
613                        {
614                            "capacity": "1200",
615                            "keyName": "1_4_TB_LOCAL_STORAGE_DEDICATED_HOST_CAPACITY",
616                            "categories": [
617                                {
618                                    "categoryCode": "dedicated_host_disk"
619                                }
620                            ]
621                        },
622                        {
623                            "capacity": "242",
624                            "keyName": "242_GB_RAM",
625                            "categories": [
626                                {
627                                    "categoryCode": "dedicated_host_ram"
628                                }
629                            ]
630                        }
631                    ],
632                    "prices": [
633                        {
634                            "itemId": 12345,
635                            "recurringFee": "2099",
636                            "hourlyRecurringFee": "3.164",
637                            "id": 12345,
638                        }
639                    ],
640                    "keyName": "56_CORES_X_242_RAM_X_1_4_TB",
641                    "id": 12345,
642                    "itemCategory": {
643                        "categoryCode": "dedicated_virtual_hosts"
644                    },
645                }
646            ],
647            "regions": [
648                {
649                    "location": {
650                        "locationPackageDetails": [
651                            {
652                                "locationId": 12345,
653                                "packageId": 813
654                            }
655                        ],
656                        "location": {
657                            "id": 12345,
658                            "name": "ams01",
659                            "longName": "Amsterdam 1"
660                        }
661                    },
662                    "keyname": "AMSTERDAM",
663                    "description": "AMS01 - Amsterdam",
664                    "sortOrder": 0
665                },
666                {
667                    "location": {
668                        "locationPackageDetails": [
669                            {
670                                "isAvailable": 1,
671                                "locationId": 12345,
672                                "packageId": 813
673                            }
674                        ],
675                        "location": {
676                            "id": 12345,
677                            "name": "dal05",
678                            "longName": "Dallas 5"
679                        }
680                    },
681                    "keyname": "DALLAS05",
682                    "description": "DAL05 - Dallas",
683                }
684
685            ],
686            "id": 813,
687            "description": "Dedicated Host"
688        }
689
690        return package
691
692    def test_list_guests(self):
693        results = self.dedicated_host.list_guests(12345)
694
695        for result in results:
696            self.assertIn(result['id'], [200, 202])
697        self.assert_called_with('SoftLayer_Virtual_DedicatedHost', 'getGuests', identifier=12345)
698
699    def test_list_guests_with_filters(self):
700        self.dedicated_host.list_guests(12345, tags=['tag1', 'tag2'], cpus=2, memory=1024,
701                                        hostname='hostname', domain='example.com', nic_speed=100,
702                                        public_ip='1.2.3.4', private_ip='4.3.2.1')
703
704        _filter = {
705            'guests': {
706                'domain': {'operation': '_= example.com'},
707                'tagReferences': {
708                    'tag': {'name': {
709                        'operation': 'in',
710                        'options': [{
711                            'name': 'data', 'value': ['tag1', 'tag2']}]}}},
712                'maxCpu': {'operation': 2},
713                'maxMemory': {'operation': 1024},
714                'hostname': {'operation': '_= hostname'},
715                'networkComponents': {'maxSpeed': {'operation': 100}},
716                'primaryIpAddress': {'operation': '_= 1.2.3.4'},
717                'primaryBackendIpAddress': {'operation': '_= 4.3.2.1'}
718            }
719        }
720        self.assert_called_with('SoftLayer_Virtual_DedicatedHost', 'getGuests',
721                                identifier=12345, filter=_filter)
722