blob: 674ebdde9ba4168af1a1464c7ec8b716b474a161 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import json
from unittest.mock import Mock, call
from libcloud.test import unittest
from libcloud.compute.base import NodeSize, NodeImage, NodeLocation, NodeAuthSSHKey
from libcloud.common.upcloud import (
PlanPrice,
UpcloudNodeDestroyer,
UpcloudNodeOperations,
UpcloudTimeoutException,
UpcloudCreateNodeRequestBody,
_StorageDevice,
)
class TestUpcloudCreateNodeRequestBody(unittest.TestCase):
def setUp(self):
self.image = NodeImage(
id="01000000-0000-4000-8000-000030060200",
name="Ubuntu Server 16.04 LTS (Xenial Xerus)",
driver="",
extra={"type": "template"},
)
self.location = NodeLocation(id="fi-hel1", name="Helsinki #1", country="FI", driver="")
self.size = NodeSize(
id="1xCPU-1GB",
name="1xCPU-1GB",
ram=1024,
disk=30,
bandwidth=2048,
extra={"core_number": 1, "storage_tier": "maxiops"},
price=None,
driver="",
)
def test_creating_node_from_template_image(self):
body = UpcloudCreateNodeRequestBody(
name="ts", image=self.image, location=self.location, size=self.size
)
json_body = body.to_json()
dict_body = json.loads(json_body)
expected_body = {
"server": {
"title": "ts",
"hostname": "localhost",
"plan": "1xCPU-1GB",
"zone": "fi-hel1",
"login_user": {"username": "root", "create_password": "yes"},
"storage_devices": {
"storage_device": [
{
"action": "clone",
"title": "Ubuntu Server 16.04 LTS (Xenial Xerus)",
"storage": "01000000-0000-4000-8000-000030060200",
"size": 30,
"tier": "maxiops",
}
]
},
}
}
self.assertDictEqual(expected_body, dict_body)
def test_creating_node_from_cdrom_image(self):
image = NodeImage(
id="01000000-0000-4000-8000-000030060200",
name="Ubuntu Server 16.04 LTS (Xenial Xerus)",
driver="",
extra={"type": "cdrom"},
)
body = UpcloudCreateNodeRequestBody(
name="ts", image=image, location=self.location, size=self.size
)
json_body = body.to_json()
dict_body = json.loads(json_body)
expected_body = {
"server": {
"title": "ts",
"hostname": "localhost",
"plan": "1xCPU-1GB",
"zone": "fi-hel1",
"login_user": {"username": "root", "create_password": "yes"},
"storage_devices": {
"storage_device": [
{
"action": "create",
"size": 30,
"tier": "maxiops",
"title": "Ubuntu Server 16.04 LTS (Xenial Xerus)",
},
{
"action": "attach",
"storage": "01000000-0000-4000-8000-000030060200",
"type": "cdrom",
},
]
},
}
}
self.assertDictEqual(expected_body, dict_body)
def test_creating_node_using_ssh_keys(self):
auth = NodeAuthSSHKey("sshkey")
body = UpcloudCreateNodeRequestBody(
name="ts",
image=self.image,
location=self.location,
size=self.size,
auth=auth,
)
json_body = body.to_json()
dict_body = json.loads(json_body)
expected_body = {
"server": {
"title": "ts",
"hostname": "localhost",
"plan": "1xCPU-1GB",
"zone": "fi-hel1",
"login_user": {
"username": "root",
"ssh_keys": {"ssh_key": ["sshkey"]},
},
"storage_devices": {
"storage_device": [
{
"action": "clone",
"size": 30,
"title": "Ubuntu Server 16.04 LTS (Xenial Xerus)",
"tier": "maxiops",
"storage": "01000000-0000-4000-8000-000030060200",
}
]
},
}
}
self.assertDictEqual(expected_body, dict_body)
def test_creating_node_using_hostname(self):
body = UpcloudCreateNodeRequestBody(
name="ts",
image=self.image,
location=self.location,
size=self.size,
ex_hostname="myhost.upcloud.com",
)
json_body = body.to_json()
dict_body = json.loads(json_body)
expected_body = {
"server": {
"title": "ts",
"hostname": "myhost.upcloud.com",
"plan": "1xCPU-1GB",
"zone": "fi-hel1",
"login_user": {"username": "root", "create_password": "yes"},
"storage_devices": {
"storage_device": [
{
"action": "clone",
"title": "Ubuntu Server 16.04 LTS (Xenial Xerus)",
"storage": "01000000-0000-4000-8000-000030060200",
"tier": "maxiops",
"size": 30,
}
]
},
}
}
self.assertDictEqual(expected_body, dict_body)
def test_creating_node_with_non_default_username(self):
body = UpcloudCreateNodeRequestBody(
name="ts",
image=self.image,
location=self.location,
size=self.size,
ex_username="someone",
)
json_body = body.to_json()
dict_body = json.loads(json_body)
login_user = dict_body["server"]["login_user"]
self.assertDictEqual({"username": "someone", "create_password": "yes"}, login_user)
class TestStorageDevice(unittest.TestCase):
def setUp(self):
self.image = NodeImage(
id="01000000-0000-4000-8000-000030060200",
name="Ubuntu Server 16.04 LTS (Xenial Xerus)",
driver="",
extra={"type": "template"},
)
self.size = NodeSize(
id="1xCPU-1GB",
name="1xCPU-1GB",
ram=1024,
disk=30,
bandwidth=2048,
extra={"core_number": 1},
price=None,
driver="",
)
def test_storage_tier_default_value(self):
storagedevice = _StorageDevice(self.image, self.size)
d = storagedevice.to_dict()
self.assertEqual(d["storage_device"][0]["tier"], "maxiops")
def test_storage_tier_given(self):
self.size.extra["storage_tier"] = "hdd"
storagedevice = _StorageDevice(self.image, self.size)
d = storagedevice.to_dict()
self.assertEqual(d["storage_device"][0]["tier"], "hdd")
class TestUpcloudNodeDestroyer(unittest.TestCase):
def setUp(self):
self.mock_sleep = Mock()
self.mock_operations = Mock(spec=UpcloudNodeOperations)
self.destroyer = UpcloudNodeDestroyer(self.mock_operations, sleep_func=self.mock_sleep)
def test_node_already_in_stopped_state(self):
self.mock_operations.get_node_state.side_effect = ["stopped"]
self.assertTrue(self.destroyer.destroy_node(1))
self.assertTrue(self.mock_operations.stop_node.call_count == 0)
self.mock_operations.destroy_node.assert_called_once_with(1)
def test_node_in_error_state(self):
self.mock_operations.get_node_state.side_effect = ["error"]
self.assertFalse(self.destroyer.destroy_node(1))
self.assertTrue(self.mock_operations.stop_node.call_count == 0)
self.assertTrue(self.mock_operations.destroy_node.call_count == 0)
def test_node_in_started_state(self):
self.mock_operations.get_node_state.side_effect = ["started", "stopped"]
self.assertTrue(self.destroyer.destroy_node(1))
self.mock_operations.stop_node.assert_called_once_with(1)
self.mock_operations.destroy_node.assert_called_once_with(1)
def test_node_in_maintenace_state(self):
self.mock_operations.get_node_state.side_effect = [
"maintenance",
"maintenance",
None,
]
self.assertTrue(self.destroyer.destroy_node(1))
self.mock_sleep.assert_has_calls(
[call(self.destroyer.WAIT_AMOUNT), call(self.destroyer.WAIT_AMOUNT)]
)
self.assertTrue(self.mock_operations.stop_node.call_count == 0)
self.assertTrue(self.mock_operations.destroy_node.call_count == 0)
def test_node_statys_in_started_state_for_awhile(self):
self.mock_operations.get_node_state.side_effect = [
"started",
"started",
"stopped",
]
self.assertTrue(self.destroyer.destroy_node(1))
# Only one all for stop should be done
self.mock_operations.stop_node.assert_called_once_with(1)
self.mock_sleep.assert_has_calls([call(self.destroyer.WAIT_AMOUNT)])
self.mock_operations.destroy_node.assert_called_once_with(1)
def test_reuse(self):
"""Verify that internal flag self.destroyer._stop_node is handled properly"""
self.mock_operations.get_node_state.side_effect = [
"started",
"stopped",
"started",
"stopped",
]
self.assertTrue(self.destroyer.destroy_node(1))
self.assertTrue(self.destroyer.destroy_node(1))
self.assertEqual(self.mock_sleep.call_count, 0)
self.assertEqual(self.mock_operations.stop_node.call_count, 2)
def test_timeout(self):
self.mock_operations.get_node_state.side_effect = ["maintenance"] * 50
self.assertRaises(UpcloudTimeoutException, self.destroyer.destroy_node, 1)
def test_timeout_reuse(self):
"""Verify sleep count is handled properly"""
self.mock_operations.get_node_state.side_effect = ["maintenance"] * 50
self.assertRaises(UpcloudTimeoutException, self.destroyer.destroy_node, 1)
self.mock_operations.get_node_state.side_effect = ["maintenance", None]
self.assertTrue(self.destroyer.destroy_node(1))
class TestPlanPrice(unittest.TestCase):
def setUp(self):
prices = [
{"name": "uk-lon1", "server_plan_1xCPU-1GB": {"amount": 1, "price": 1.488}},
{"name": "fi-hel1", "server_plan_1xCPU-1GB": {"amount": 1, "price": 1.588}},
]
self.pp = PlanPrice(prices)
def test_zone_prices(self):
location = NodeLocation(id="fi-hel1", name="Helsinki #1", country="FI", driver=None)
self.assertEqual(self.pp.get_price("1xCPU-1GB", location), 1.588)
def test_plan_not_found_in_zone(self):
location = NodeLocation(id="no_such_location", name="", country="", driver=None)
self.assertIsNone(self.pp.get_price("1xCPU-1GB", location))
def test_no_location_given(self):
self.assertIsNone(self.pp.get_price("1xCPU-1GB"))
if __name__ == "__main__":
sys.exit(unittest.main())