You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by qu...@apache.org on 2017/09/27 03:12:44 UTC
[01/14] libcloud git commit: Add changes for #1102
Repository: libcloud
Updated Branches:
refs/heads/trunk 5892fa1be -> d8be2d472
Add changes for #1102
Closes #1102
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d8be2d47
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d8be2d47
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d8be2d47
Branch: refs/heads/trunk
Commit: d8be2d472b4fbd6c88d6e4e1d00f2aeda11a77a7
Parents: f37b7c0
Author: Quentin Pradet <qu...@apache.org>
Authored: Wed Sep 27 06:57:09 2017 +0400
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
CHANGES.rst | 3 +++
1 file changed, 3 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d8be2d47/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 527ecd4..ea472eb 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -7,6 +7,9 @@ Changes in Apach Libcloud in development
Compute
~~~~~~~
+- New driver for UpCloud (GITHUB-1102)
+ [Mika Lackman, Ilari Mäkelä]
+
- [EC2] Add new x1.16xlarge and x1e.32xlarge instance type. (GITHUB-1101)
[@zulupro]
[09/14] libcloud git commit: Upcloud renamed to UpCloud
Posted by qu...@apache.org.
Upcloud renamed to UpCloud
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0e0b6831
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0e0b6831
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0e0b6831
Branch: refs/heads/trunk
Commit: 0e0b68319ba8771122a1418bd8bb9ac351ba9ed3
Parents: 5326c9a
Author: Mika Lackman <mi...@upcloud.com>
Authored: Sun Sep 24 19:38:54 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/compute/types.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/0e0b6831/libcloud/compute/types.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py
index b360c0e..0de0497 100644
--- a/libcloud/compute/types.py
+++ b/libcloud/compute/types.py
@@ -98,7 +98,7 @@ class Provider(Type):
:cvar RACKSPACE_FIRST_GEN: Rackspace First Gen Cloud Servers
:cvar RIMUHOSTING: RimuHosting.com
:cvar TERREMARK: Terremark
- :cvar UPCLOUD: Upcloud
+ :cvar UPCLOUD: UpCloud
:cvar VCL: VCL driver
:cvar VCLOUD: vmware vCloud
:cvar VPSNET: VPS.net
[12/14] libcloud git commit: Changed data centres to data centers
Posted by qu...@apache.org.
Changed data centres to data centers
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a2dc54a6
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a2dc54a6
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a2dc54a6
Branch: refs/heads/trunk
Commit: a2dc54a6f2abc070bfe167e1d6a1ec9686ba451e
Parents: d78edb8
Author: Ilari Mäkelä <il...@users.noreply.github.com>
Authored: Tue Sep 26 12:53:00 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
docs/compute/drivers/upcloud.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/a2dc54a6/docs/compute/drivers/upcloud.rst
----------------------------------------------------------------------
diff --git a/docs/compute/drivers/upcloud.rst b/docs/compute/drivers/upcloud.rst
index b9a0bf3..09ae874 100644
--- a/docs/compute/drivers/upcloud.rst
+++ b/docs/compute/drivers/upcloud.rst
@@ -1,14 +1,14 @@
UpCloud Driver Documentation
===============================
`UpCloud`_ is a Finnish IaaS provider offering high performance servers
-from data centres based in multiple countries.
+from data centers based in multiple countries.
.. figure:: /_static/images/provider_logos/upcloud.png
:align: center
:width: 300
:target: https://www.upcloud.com/
-UpCloud currently operates globally from six (6) data centres:
+UpCloud currently operates globally from six (6) data centers:
* Amsterdam, Netherlands
* Chicago, USA
[03/14] libcloud git commit: Updated upcloud.rst
Posted by qu...@apache.org.
Updated upcloud.rst
- Revised the wording
- Added 'Enabling API access' section
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/fdbd943b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/fdbd943b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/fdbd943b
Branch: refs/heads/trunk
Commit: fdbd943b103c1bd2873b5d9d2b67140fa6002cb7
Parents: 9a97e3b
Author: Ilari Mäkelä <il...@users.noreply.github.com>
Authored: Tue Sep 26 10:47:18 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
docs/compute/drivers/upcloud.rst | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/fdbd943b/docs/compute/drivers/upcloud.rst
----------------------------------------------------------------------
diff --git a/docs/compute/drivers/upcloud.rst b/docs/compute/drivers/upcloud.rst
index 4c6a400..b9a0bf3 100644
--- a/docs/compute/drivers/upcloud.rst
+++ b/docs/compute/drivers/upcloud.rst
@@ -1,7 +1,7 @@
UpCloud Driver Documentation
===============================
-`UpCloud`_ is a Finnish IaaS provider offering the most high performance
-servers with extremely redundant infrastructure to the most demanding customers.
+`UpCloud`_ is a Finnish IaaS provider offering high performance servers
+from data centres based in multiple countries.
.. figure:: /_static/images/provider_logos/upcloud.png
:align: center
@@ -26,6 +26,20 @@ driver constructor:
* ``username`` - Your API access enabled users username
* ``password`` - Your API access enabled users password
-You can setup your API access enabled user account from https://my.upcloud.com/account
+Enabling API access
+-------------------
+
+To allow API access to your UpCloud account, you first need to enable the API
+permissions by visiting `My Account -> User accounts`_ in your UpCloud Control
+Panel. We recommend you to set up a sub-account specifically for the API usage
+with its own username and password, as it allows you to assign specific permissions
+for increased security.
+
+Click **Add user** and fill in the required details, and check the
+“**Allow API connections**” checkbox to enable API for the user. You can also
+limit the API connections to a specific IP address or address range for additional
+security. Once you are done entering the user information, hit the **Save** button
+at the bottom of the page to create the new username.
.. _`UpCloud`: https://www.upcloud.com/
+.. _`My Account -> User accounts`: https://my.upcloud.com/account
[14/14] libcloud git commit: Renamed SERVER_STATE to NODE_STATE_MAP
and moved it to UpcloudDriver for better consistency with other drivers
Posted by qu...@apache.org.
Renamed SERVER_STATE to NODE_STATE_MAP and moved it to UpcloudDriver for better consistency with other drivers
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/e7df9487
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/e7df9487
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/e7df9487
Branch: refs/heads/trunk
Commit: e7df94873dc0e2f9c5bfdd358fe99da6eda82c04
Parents: a2dc54a
Author: Mika Lackman <mi...@upcloud.com>
Authored: Tue Sep 26 15:33:23 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/compute/drivers/upcloud.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/e7df9487/libcloud/compute/drivers/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/upcloud.py b/libcloud/compute/drivers/upcloud.py
index d2e0314..c9c762e 100644
--- a/libcloud/compute/drivers/upcloud.py
+++ b/libcloud/compute/drivers/upcloud.py
@@ -28,13 +28,6 @@ from libcloud.common.upcloud import UpcloudCreateNodeRequestBody
from libcloud.common.upcloud import UpcloudNodeDestroyer
from libcloud.common.upcloud import UpcloudNodeOperations
-SERVER_STATE = {
- 'started': NodeState.RUNNING,
- 'stopped': NodeState.STOPPED,
- 'maintenance': NodeState.RECONFIGURING,
- 'error': NodeState.ERROR
-}
-
class UpcloudResponse(JsonResponse):
"""
@@ -92,6 +85,13 @@ class UpcloudDriver(NodeDriver):
connectionCls = UpcloudConnection
features = {'create_node': ['ssh_key', 'generates_password']}
+ NODE_STATE_MAP = {
+ 'started': NodeState.RUNNING,
+ 'stopped': NodeState.STOPPED,
+ 'maintenance': NodeState.RECONFIGURING,
+ 'error': NodeState.ERROR
+ }
+
def __init__(self, username, password, **kwargs):
super(UpcloudDriver, self).__init__(key=username, secret=password,
**kwargs)
@@ -236,7 +236,7 @@ class UpcloudDriver(NodeDriver):
extra['password'] = server['password']
return Node(id=server['uuid'],
name=server['title'],
- state=state or SERVER_STATE[server['state']],
+ state=state or self.NODE_STATE_MAP[server['state']],
public_ips=public_ips,
private_ips=private_ips,
driver=self,
[10/14] libcloud git commit: Added upcloud.png to provider logos
Posted by qu...@apache.org.
Added upcloud.png to provider logos
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d78edb8f
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d78edb8f
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d78edb8f
Branch: refs/heads/trunk
Commit: d78edb8fb1e6404f49576fb670b046071c5f8fa5
Parents: fdbd943
Author: Ilari Mäkelä <il...@i28.fi>
Authored: Tue Sep 26 10:52:33 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
docs/_static/images/provider_logos/upcloud.png | Bin 0 -> 20107 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d78edb8f/docs/_static/images/provider_logos/upcloud.png
----------------------------------------------------------------------
diff --git a/docs/_static/images/provider_logos/upcloud.png b/docs/_static/images/provider_logos/upcloud.png
new file mode 100644
index 0000000..5b5f205
Binary files /dev/null and b/docs/_static/images/provider_logos/upcloud.png differ
[04/14] libcloud git commit: New compute driver for UpCloud
Posted by qu...@apache.org.
New compute driver for UpCloud
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/abbd9bb6
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/abbd9bb6
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/abbd9bb6
Branch: refs/heads/trunk
Commit: abbd9bb63f8b1295bc67fbcf8f271f89ed79e4d6
Parents: 5892fa1
Author: Mika Lackman <mi...@upcloud.com>
Authored: Mon Aug 14 14:03:29 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/common/upcloud.py | 183 +++++++++
libcloud/compute/drivers/upcloud.py | 277 +++++++++++++
libcloud/compute/types.py | 2 +
libcloud/test/common/test_upcloud.py | 212 ++++++++++
.../compute/fixtures/upcloud/api_1_2_plan.json | 38 ++
.../fixtures/upcloud/api_1_2_server.json | 22 +
...er_00893c98-5d5a-4363-b177-88df518a2b60.json | 58 +++
...er_00f8c525-7e62-4108-8115-3958df5b43dc.json | 57 +++
...525-7e62-4108-8115-3958df5b43dc_restart.json | 57 +++
.../upcloud/api_1_2_server_from_cdrom.json | 65 +++
.../upcloud/api_1_2_server_from_template.json | 59 +++
.../fixtures/upcloud/api_1_2_storage_cdrom.json | 411 +++++++++++++++++++
.../upcloud/api_1_2_storage_template.json | 114 +++++
.../compute/fixtures/upcloud/api_1_2_zone.json | 30 ++
.../upcloud/api_1_2_zone_failed_auth.json | 6 +
libcloud/test/compute/test_upcloud.py | 248 +++++++++++
libcloud/test/secrets.py-dist | 1 +
17 files changed, 1840 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/common/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/common/upcloud.py b/libcloud/common/upcloud.py
new file mode 100644
index 0000000..432606a
--- /dev/null
+++ b/libcloud/common/upcloud.py
@@ -0,0 +1,183 @@
+# 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 json
+import time
+
+from libcloud.common.exceptions import BaseHTTPError
+
+
+class UpcloudTimeoutException(Exception):
+ pass
+
+
+class UpcloudCreateNodeRequestBody(object):
+ """Body of the create_node request
+
+ Takes the create_node arguments (**kwargs) and constructs the request body
+ """
+ def __init__(self, user_id, name, size, image, location, auth=None):
+ self.body = {
+ 'server': {
+ 'title': name,
+ 'hostname': 'localhost',
+ 'plan': size.id,
+ 'zone': location.id,
+ 'login_user': _LoginUser(user_id, auth).to_dict(),
+ 'storage_devices': _StorageDevice(image, size).to_dict()
+ }
+ }
+
+ def to_json(self):
+ """Serializes the body to json"""
+ return json.dumps(self.body)
+
+
+class UpcloudNodeDestroyer(object):
+ """Destroyes the node.
+ Node must be first stopped and then it can be
+ destroyed"""
+
+ WAIT_AMOUNT = 2
+ SLEEP_COUNT_TO_TIMEOUT = 20
+
+ def __init__(self, upcloud_node_operations, sleep_func=None):
+ self._operations = upcloud_node_operations
+ self._sleep_func = sleep_func or time.sleep
+ self._sleep_count = 0
+
+ def destroy_node(self, node_id):
+ self._stop_called = False
+ self._sleep_count = 0
+ return self._do_destroy_node(node_id)
+
+ def _do_destroy_node(self, node_id):
+ state = self._operations.node_state(node_id)
+ if state == 'stopped':
+ self._operations.destroy_node(node_id)
+ return True
+ elif state == 'error':
+ return False
+ elif state == 'started':
+ if not self._stop_called:
+ self._operations.stop_node(node_id)
+ self._stop_called = True
+ else:
+ # Waiting for started state to change and
+ # not calling stop again
+ self._sleep()
+ return self._do_destroy_node(node_id)
+ elif state == 'maintenance':
+ # Lets wait maintenace state to go away and retry destroy
+ self._sleep()
+ return self._do_destroy_node(node_id)
+ elif state is None: # Server not found any more
+ return True
+
+ def _sleep(self):
+ if self._sleep_count > self.SLEEP_COUNT_TO_TIMEOUT:
+ raise UpcloudTimeoutException("Timeout, could not destroy node")
+ self._sleep_count += 1
+ self._sleep_func(self.WAIT_AMOUNT)
+
+
+class UpcloudNodeOperations(object):
+
+ def __init__(self, connection):
+ self.connection = connection
+
+ def stop_node(self, node_id):
+ body = {
+ 'stop_server': {
+ 'stop_type': 'hard'
+ }
+ }
+ self.connection.request('1.2/server/{0}/stop'.format(node_id),
+ method='POST',
+ data=json.dumps(body))
+
+ def node_state(self, node_id):
+ action = '1.2/server/{0}'.format(node_id)
+ try:
+ response = self.connection.request(action)
+ return response.object['server']['state']
+ except BaseHTTPError as e:
+ if e.code == 404:
+ return None
+ raise
+
+ def destroy_node(self, node_id):
+ self.connection.request('1.2/server/{0}'.format(node_id),
+ method='DELETE')
+
+
+class _LoginUser(object):
+
+ def __init__(self, user_id, auth=None):
+ self.user_id = user_id
+ self.auth = auth
+
+ def to_dict(self):
+ login_user = {'username': self.user_id}
+ if self.auth is not None:
+ login_user['ssh_keys'] = {
+ 'ssh_key': [self.auth.pubkey]
+ }
+ else:
+ login_user['create_password'] = 'yes'
+
+ return login_user
+
+
+class _StorageDevice(object):
+
+ def __init__(self, image, size):
+ self.image = image
+ self.size = size
+
+ def to_dict(self):
+ extra = self.image.extra
+ if extra['type'] == 'template':
+ return self._storage_device_for_template_image()
+ elif extra['type'] == 'cdrom':
+ return self._storage_device_for_cdrom_image()
+
+ def _storage_device_for_template_image(self):
+ storage_devices = {
+ 'storage_device': [{
+ 'action': 'clone',
+ 'title': self.image.name,
+ 'storage': self.image.id
+ }]
+ }
+ return storage_devices
+
+ def _storage_device_for_cdrom_image(self):
+ storage_devices = {
+ 'storage_device': [
+ {
+ 'action': 'create',
+ 'title': self.image.name,
+ 'size': self.size.disk,
+ 'tier': self.size.extra['storage_tier']
+
+ },
+ {
+ 'action': 'attach',
+ 'storage': self.image.id,
+ 'type': 'cdrom'
+ }
+ ]
+ }
+ return storage_devices
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/compute/drivers/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/upcloud.py b/libcloud/compute/drivers/upcloud.py
new file mode 100644
index 0000000..b9daf84
--- /dev/null
+++ b/libcloud/compute/drivers/upcloud.py
@@ -0,0 +1,277 @@
+# 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.
+"""
+Upcloud node driver
+"""
+import base64
+import json
+
+from libcloud.utils.py3 import httplib, b
+from libcloud.compute.base import NodeDriver, NodeLocation, NodeSize
+from libcloud.compute.base import NodeImage, Node, NodeState
+from libcloud.compute.types import Provider
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse
+from libcloud.common.types import InvalidCredsError
+from libcloud.common.upcloud import UpcloudCreateNodeRequestBody
+from libcloud.common.upcloud import UpcloudNodeDestroyer
+from libcloud.common.upcloud import UpcloudNodeOperations
+
+SERVER_STATE = {
+ 'started': NodeState.RUNNING,
+ 'stopped': NodeState.STOPPED,
+ 'maintenance': NodeState.RECONFIGURING,
+ 'error': NodeState.ERROR
+}
+
+
+class UpcloudResponse(JsonResponse):
+ """Response class for UpcloudDriver"""
+
+ def success(self):
+ if self.status == httplib.NO_CONTENT:
+ return True
+ return super(UpcloudResponse, self).success()
+
+ def parse_error(self):
+ data = self.parse_body()
+ if self.status == httplib.UNAUTHORIZED:
+ raise InvalidCredsError(value=data['error']['error_message'])
+ return data
+
+
+class UpcloudConnection(ConnectionUserAndKey):
+ """Connection class for UpcloudDriver"""
+ host = 'api.upcloud.com'
+ responseCls = UpcloudResponse
+
+ def add_default_headers(self, headers):
+ """Adds headers that are needed for all requests"""
+ headers['Authorization'] = self._basic_auth()
+ headers['Accept'] = 'application/json'
+ headers['Content-Type'] = 'application/json'
+ return headers
+
+ def _basic_auth(self):
+ """Constructs basic auth header content string"""
+ credentials = b("{0}:{1}".format(self.user_id, self.key))
+ credentials = base64.b64encode(credentials)
+ return 'Basic {0}'.format(credentials.decode('ascii'))
+
+
+class UpcloudDriver(NodeDriver):
+ """Upcloud node driver
+
+ :keyword username: Username required for authentication
+ :type username: ``str``
+
+ :keyword password: Password required for authentication
+ :type password: ``str``
+ """
+ type = Provider.UPCLOUD
+ name = 'Upcloud'
+ website = 'https://www.upcloud.com'
+ connectionCls = UpcloudConnection
+ features = {'create_node': ['ssh_key', 'generates_password']}
+
+ def __init__(self, username, password, **kwargs):
+ super(UpcloudDriver, self).__init__(key=username, secret=password,
+ **kwargs)
+
+ def list_locations(self):
+ """
+ List available locations for deployment
+
+ :rtype: ``list`` of :class:`NodeLocation`
+ """
+ response = self.connection.request('1.2/zone')
+ return self._to_node_locations(response.object['zones']['zone'])
+
+ def list_sizes(self):
+ """
+ List available plans
+
+ :rtype: ``list`` of :class:`NodeSize`
+ """
+ response = self.connection.request('1.2/plan')
+ return self._to_node_sizes(response.object['plans']['plan'])
+
+ def list_images(self):
+ """
+ List available distributions.
+
+ :rtype: ``list`` of :class:`NodeImage`
+ """
+ response = self.connection.request('1.2/storage/template')
+ obj = response.object
+ response = self.connection.request('1.2/storage/cdrom')
+ storage = response.object['storages']['storage']
+ obj['storages']['storage'].extend(storage)
+ return self._to_node_images(obj['storages']['storage'])
+
+ def create_node(self, name, size, image, location, auth=None, **kwargs):
+ """
+ Creates instance to upcloud.
+
+ If auth is not given then password will be generated.
+
+ :param name: String with a name for this new node (required)
+ :type name: ``str``
+
+ :param size: The size of resources allocated to this node.
+ (required)
+ :type size: :class:`.NodeSize`
+
+ :param image: OS Image to boot on node. (required)
+ :type image: :class:`.NodeImage`
+
+ :param location: Which data center to create a node in. If empty,
+ undefined behavior will be selected. (optional)
+ :type location: :class:`.NodeLocation`
+
+ :param auth: Initial authentication information for the node
+ (optional)
+ :type auth: :class:`.NodeAuthSSHKey`
+
+ :return: The newly created node.
+ :rtype: :class:`.Node`
+ """
+ body = UpcloudCreateNodeRequestBody(user_id=self.connection.user_id,
+ name=name, size=size, image=image,
+ location=location, auth=auth)
+ response = self.connection.request('1.2/server',
+ method='POST',
+ data=body.to_json())
+ server = response.object['server']
+ # Upcloud server's are in maintenace state when goind
+ # from state to other, it is safe to assume STARTING state
+ return self._to_node(server, state=NodeState.STARTING)
+
+ def list_nodes(self):
+ """
+ List nodes
+
+ :return: List of node objects
+ :rtype: ``list`` of :class:`Node`
+ """
+ servers = []
+ for nid in self._node_ids():
+ response = self.connection.request('1.2/server/{0}'.format(nid))
+ servers.append(response.object['server'])
+ return self._to_nodes(servers)
+
+ def reboot_node(self, node):
+ """
+ Reboot the given node
+
+ :param node: the node to reboot
+ :type node: :class:`Node`
+
+ :rtype: ``bool``
+ """
+ body = {
+ 'restart_server': {
+ 'stop_type': 'hard'
+ }
+ }
+ self.connection.request('1.2/server/{0}/restart'.format(node.id),
+ method='POST',
+ data=json.dumps(body))
+ return True
+
+ def destroy_node(self, node):
+ """
+ Destroy the given node
+
+ The disk resources, attached to node, will not be removed.
+
+ :param node: the node to destroy
+ :type node: :class:`Node`
+
+ :rtype: ``bool``
+ """
+
+ operations = UpcloudNodeOperations(self.connection)
+ destroyer = UpcloudNodeDestroyer(operations)
+ return destroyer.destroy_node(node.id)
+
+ def _node_ids(self):
+ """Returns list of server uids currently on upcloud"""
+ response = self.connection.request('1.2/server')
+ servers = response.object['servers']['server']
+ return [server['uuid'] for server in servers]
+
+ def _to_nodes(self, servers):
+ return [self._to_node(server) for server in servers]
+
+ def _to_node(self, server, state=None):
+ ip_addresses = server['ip_addresses']['ip_address']
+ public_ips = [ip['address'] for ip in ip_addresses
+ if ip['access'] == 'public']
+ private_ips = [ip['address'] for ip in ip_addresses
+ if ip['access'] == 'private']
+
+ extra = {'vnc_password': server['vnc_password']}
+ if 'password' in server:
+ extra['password'] = server['password']
+ return Node(id=server['uuid'],
+ name=server['title'],
+ state=state or SERVER_STATE[server['state']],
+ public_ips=public_ips,
+ private_ips=private_ips,
+ driver=self,
+ extra=extra)
+
+ def _to_node_locations(self, zones):
+ return [self._construct_node_location(zone) for zone in zones]
+
+ def _construct_node_location(self, zone):
+ return NodeLocation(id=zone['id'],
+ name=zone['description'],
+ country=self._parse_country(zone['id']),
+ driver=self)
+
+ def _parse_country(self, zone_id):
+ """Parses the country information out of zone_id.
+ Zone_id format [country]_[city][number], like fi_hel1"""
+ return zone_id.split('-')[0].upper()
+
+ def _to_node_sizes(self, plans):
+ return [self._construct_node_size(plan) for plan in plans]
+
+ def _construct_node_size(self, plan):
+ extra = self._copy_dict(('core_number', 'storage_tier'), plan)
+ return NodeSize(id=plan['name'], name=plan['name'],
+ ram=plan['memory_amount'],
+ disk=plan['storage_size'],
+ bandwidth=plan['public_traffic_out'],
+ price=None, driver=self,
+ extra=extra)
+
+ def _to_node_images(self, images):
+ return [self._construct_node_image(image) for image in images]
+
+ def _construct_node_image(self, image):
+ extra = self._copy_dict(('access', 'license',
+ 'size', 'state', 'type'), image)
+ return NodeImage(id=image['uuid'],
+ name=image['title'],
+ driver=self,
+ extra=extra)
+
+ def _copy_dict(self, keys, d):
+ extra = {}
+ for key in keys:
+ extra[key] = d[key]
+ return extra
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/compute/types.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py
index deae506..b360c0e 100644
--- a/libcloud/compute/types.py
+++ b/libcloud/compute/types.py
@@ -98,6 +98,7 @@ class Provider(Type):
:cvar RACKSPACE_FIRST_GEN: Rackspace First Gen Cloud Servers
:cvar RIMUHOSTING: RimuHosting.com
:cvar TERREMARK: Terremark
+ :cvar UPCLOUD: Upcloud
:cvar VCL: VCL driver
:cvar VCLOUD: vmware vCloud
:cvar VPSNET: VPS.net
@@ -161,6 +162,7 @@ class Provider(Type):
SKALICLOUD = 'skalicloud'
SOFTLAYER = 'softlayer'
TERREMARK = 'terremark'
+ UPCLOUD = 'upcloud'
VCL = 'vcl'
VCLOUD = 'vcloud'
VOXEL = 'voxel'
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/common/test_upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_upcloud.py b/libcloud/test/common/test_upcloud.py
new file mode 100644
index 0000000..76dd9c1
--- /dev/null
+++ b/libcloud/test/common/test_upcloud.py
@@ -0,0 +1,212 @@
+# 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 mock import Mock, call
+
+from libcloud.common.upcloud import UpcloudCreateNodeRequestBody, UpcloudNodeDestroyer, UpcloudNodeOperations
+from libcloud.common.upcloud import UpcloudTimeoutException
+from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, NodeAuthSSHKey
+from libcloud.test import unittest
+
+
+class TestUpcloudCreateNodeRequestBody(unittest.TestCase):
+
+ def test_creating_node_from_template_image(self):
+ image = NodeImage(id='01000000-0000-4000-8000-000030060200',
+ name='Ubuntu Server 16.04 LTS (Xenial Xerus)',
+ driver='',
+ extra={'type': 'template'})
+ location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver='')
+ size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048,
+ extra={'core_number': 1, 'storage_tier': 'maxiops'}, price=None, driver='')
+
+ body = UpcloudCreateNodeRequestBody(user_id='somename', name='ts', image=image, location=location, size=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': 'somename',
+ 'create_password': 'yes'},
+ 'storage_devices': {
+ 'storage_device': [{
+ 'action': 'clone',
+ 'title': 'Ubuntu Server 16.04 LTS (Xenial Xerus)',
+ 'storage': '01000000-0000-4000-8000-000030060200'
+ }]
+ },
+ }
+ }
+ 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'})
+ location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver='')
+ size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048,
+ extra={'core_number': 1, 'storage_tier': 'maxiops'}, price=None, driver='')
+
+ body = UpcloudCreateNodeRequestBody(user_id='somename', name='ts', image=image, location=location, size=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': 'somename',
+ '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):
+ image = NodeImage(id='01000000-0000-4000-8000-000030060200',
+ name='Ubuntu Server 16.04 LTS (Xenial Xerus)',
+ driver='',
+ extra={'type': 'template'})
+ location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver='')
+ size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048,
+ extra={'core_number': 1, 'storage_tier': 'maxiops'}, price=None, driver='')
+ auth = NodeAuthSSHKey('sshkey')
+
+ body = UpcloudCreateNodeRequestBody(user_id='somename', name='ts', image=image, location=location, size=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': 'somename',
+ 'ssh_keys': {
+ 'ssh_key': [
+ 'sshkey'
+ ]
+ },
+ },
+ 'storage_devices': {
+ 'storage_device': [{
+ 'action': 'clone',
+ 'title': 'Ubuntu Server 16.04 LTS (Xenial Xerus)',
+ 'storage': '01000000-0000-4000-8000-000030060200'
+ }]
+ },
+ }
+ }
+ self.assertDictEqual(expected_body, dict_body)
+
+
+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.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.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.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.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.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.node_state.side_effect = ['started', 'stopped', 'started', 'stopped']
+ self.assertTrue(self.destroyer.destroy_node(1))
+ self.assertTrue(self.destroyer.destroy_node(1))
+
+ self.assertEquals(self.mock_sleep.call_count, 0)
+ self.assertEquals(self.mock_operations.stop_node.call_count, 2)
+
+ def test_timeout(self):
+ self.mock_operations.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.node_state.side_effect = ['maintenance'] * 50
+ self.assertRaises(UpcloudTimeoutException, self.destroyer.destroy_node, 1)
+
+ self.mock_operations.node_state.side_effect = ['maintenance', None]
+ self.assertTrue(self.destroyer.destroy_node(1))
+
+
+if __name__ == '__main__':
+ sys.exit(unittest.main())
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_plan.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_plan.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_plan.json
new file mode 100644
index 0000000..c59dcf0
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_plan.json
@@ -0,0 +1,38 @@
+{
+ "plans" : {
+ "plan" : [
+ {
+ "core_number" : 1,
+ "memory_amount" : 1024,
+ "name" : "1xCPU-1GB",
+ "public_traffic_out" : 2048,
+ "storage_size" : 30,
+ "storage_tier" : "maxiops"
+ },
+ {
+ "core_number" : 2,
+ "memory_amount" : 2048,
+ "name" : "2xCPU-2GB",
+ "public_traffic_out" : 3072,
+ "storage_size" : 50,
+ "storage_tier" : "maxiops"
+ },
+ {
+ "core_number" : 4,
+ "memory_amount" : 4096,
+ "name" : "4xCPU-4GB",
+ "public_traffic_out" : 4096,
+ "storage_size" : 100,
+ "storage_tier" : "maxiops"
+ },
+ {
+ "core_number" : 6,
+ "memory_amount" : 8192,
+ "name" : "6xCPU-8GB",
+ "public_traffic_out" : 8192,
+ "storage_size" : 200,
+ "storage_tier" : "maxiops"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_server.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_server.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_server.json
new file mode 100644
index 0000000..e2a7d0a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_server.json
@@ -0,0 +1,22 @@
+{
+ "servers" : {
+ "server" : [
+ {
+ "core_number" : "1",
+ "hostname" : "localhost",
+ "license" : 0,
+ "memory_amount" : "1024",
+ "plan" : "1xCPU-1GB",
+ "plan_ipv4_bytes" : "12267",
+ "plan_ipv6_bytes" : "4644",
+ "state" : "started",
+ "tags" : {
+ "tag" : []
+ },
+ "title" : "test_server",
+ "uuid" : "00f8c525-7e62-4108-8115-3958df5b43dc",
+ "zone" : "fi-hel1"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.json
new file mode 100644
index 0000000..c99fc05
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.json
@@ -0,0 +1,58 @@
+{
+ "server" : {
+ "boot_order" : "cdrom,disk",
+ "core_number" : "1",
+ "firewall" : "off",
+ "host" : 4297867907,
+ "hostname" : "localhost",
+ "ip_addresses" : {
+ "ip_address" : [
+ {
+ "access" : "private",
+ "address" : "10.2.1.244",
+ "family" : "IPv4"
+ },
+ {
+ "access" : "public",
+ "address" : "2a04:3541:1000:500:7cae:1dff:fead:5bde",
+ "family" : "IPv6"
+ },
+ {
+ "access" : "public",
+ "address" : "83.136.254.34",
+ "family" : "IPv4",
+ "part_of_plan" : "yes"
+ }
+ ]
+ },
+ "license" : 0,
+ "memory_amount" : "1024",
+ "nic_model" : "virtio",
+ "plan" : "1xCPU-1GB",
+ "plan_ipv4_bytes" : "0",
+ "plan_ipv6_bytes" : "0",
+ "state" : "stopped",
+ "storage_devices" : {
+ "storage_device" : [
+ {
+ "address" : "virtio:0",
+ "part_of_plan" : "yes",
+ "storage" : "01839922-a675-4214-b10e-a4cf7953992f",
+ "storage_size" : 30,
+ "storage_title" : "localhost-disk0",
+ "type" : "disk"
+ }
+ ]
+ },
+ "tags" : {
+ "tag" : []
+ },
+ "timezone" : "UTC",
+ "title" : "test",
+ "uuid" : "00893c98-5d5a-4363-b177-88df518a2b60",
+ "video_model" : "cirrus",
+ "vnc" : "off",
+ "vnc_password" : "Hf7qpJs8",
+ "zone" : "uk-lon1"
+ }
+}
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json
new file mode 100644
index 0000000..1278e6e
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json
@@ -0,0 +1,57 @@
+{
+ "server" : {
+ "boot_order" : "disk",
+ "core_number" : "1",
+ "firewall" : "off",
+ "host" : 4964762243,
+ "hostname" : "localhost",
+ "ip_addresses" : {
+ "ip_address" : [
+ {
+ "access" : "private",
+ "address" : "10.1.7.68",
+ "family" : "IPv4"
+ },
+ {
+ "access" : "public",
+ "address" : "2a04:3540:1000:310:7cae:1dff:fead:19dc",
+ "family" : "IPv6"
+ },
+ {
+ "access" : "public",
+ "address" : "94.237.37.249",
+ "family" : "IPv4",
+ "part_of_plan" : "yes"
+ }
+ ]
+ },
+ "license" : 0,
+ "memory_amount" : "1024",
+ "nic_model" : "virtio",
+ "plan" : "1xCPU-1GB",
+ "plan_ipv4_bytes" : "8242",
+ "plan_ipv6_bytes" : "3440",
+ "state" : "started",
+ "storage_devices" : {
+ "storage_device" : [
+ {
+ "address" : "virtio:0",
+ "storage" : "01e5411f-37c9-4b8e-b0bb-4cad5119b3ea",
+ "storage_size" : 10,
+ "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)",
+ "type" : "disk"
+ }
+ ]
+ },
+ "tags" : {
+ "tag" : []
+ },
+ "timezone" : "UTC",
+ "title" : "test_server",
+ "uuid" : "00f8c525-7e62-4108-8115-3958df5b43dc",
+ "video_model" : "cirrus",
+ "vnc" : "off",
+ "vnc_password" : "r362XMmV",
+ "zone" : "fi-hel1"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.json
new file mode 100644
index 0000000..af904e4
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.json
@@ -0,0 +1,57 @@
+{
+ "server" : {
+ "boot_order" : "disk",
+ "core_number" : "1",
+ "firewall" : "off",
+ "host" : 4964762243,
+ "hostname" : "localhost",
+ "ip_addresses" : {
+ "ip_address" : [
+ {
+ "access" : "private",
+ "address" : "10.1.7.68",
+ "family" : "IPv4"
+ },
+ {
+ "access" : "public",
+ "address" : "2a04:3540:1000:310:7cae:1dff:fead:19dc",
+ "family" : "IPv6"
+ },
+ {
+ "access" : "public",
+ "address" : "94.237.37.249",
+ "family" : "IPv4",
+ "part_of_plan" : "yes"
+ }
+ ]
+ },
+ "license" : 0,
+ "memory_amount" : "1024",
+ "nic_model" : "virtio",
+ "plan" : "1xCPU-1GB",
+ "plan_ipv4_bytes" : "218066",
+ "plan_ipv6_bytes" : "6450",
+ "state" : "started",
+ "storage_devices" : {
+ "storage_device" : [
+ {
+ "address" : "virtio:0",
+ "storage" : "01e5411f-37c9-4b8e-b0bb-4cad5119b3ea",
+ "storage_size" : 10,
+ "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)",
+ "type" : "disk"
+ }
+ ]
+ },
+ "tags" : {
+ "tag" : []
+ },
+ "timezone" : "UTC",
+ "title" : "test_server",
+ "uuid" : "00f8c525-7e62-4108-8115-3958df5b43dc",
+ "video_model" : "cirrus",
+ "vnc" : "off",
+ "vnc_password" : "r362XMmV",
+ "zone" : "fi-hel1"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_cdrom.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_cdrom.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_cdrom.json
new file mode 100644
index 0000000..b82f8c6
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_cdrom.json
@@ -0,0 +1,65 @@
+{
+ "server" : {
+ "boot_order" : "disk",
+ "core_number" : "1",
+ "firewall" : "off",
+ "hostname" : "localhost",
+ "ip_addresses" : {
+ "ip_address" : [
+ {
+ "access" : "private",
+ "address" : "10.1.2.26",
+ "family" : "IPv4"
+ },
+ {
+ "access" : "public",
+ "address" : "2a04:3540:1000:310:7cae:1dff:fead:5683",
+ "family" : "IPv6"
+ },
+ {
+ "access" : "public",
+ "address" : "94.237.37.215",
+ "family" : "IPv4",
+ "part_of_plan" : "yes"
+ }
+ ]
+ },
+ "license" : 0,
+ "memory_amount" : "1024",
+ "nic_model" : "virtio",
+ "plan" : "1xCPU-1GB",
+ "plan_ipv4_bytes" : "0",
+ "plan_ipv6_bytes" : "0",
+ "progress" : "0",
+ "state" : "maintenance",
+ "storage_devices" : {
+ "storage_device" : [
+ {
+ "address" : "virtio:0",
+ "part_of_plan" : "yes",
+ "storage" : "01898fe2-9909-471e-b33c-59d7896b48f5",
+ "storage_size" : 30,
+ "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus), 64-bit",
+ "type" : "disk"
+ },
+ {
+ "address" : "ide:0:0",
+ "storage" : "01000000-0000-4000-8000-000030040101",
+ "storage_size" : 1,
+ "storage_title" : "Ubuntu Server 14.04 LTS",
+ "type" : "cdrom"
+ }
+ ]
+ },
+ "tags" : {
+ "tag" : []
+ },
+ "timezone" : "UTC",
+ "title" : "test_server",
+ "uuid" : "00c68ee6-e6e1-4d5f-a213-4a1e063a3cbd",
+ "video_model" : "cirrus",
+ "vnc" : "off",
+ "vnc_password" : "5C4TVPf8",
+ "zone" : "fi-hel1"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_template.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_template.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_template.json
new file mode 100644
index 0000000..cde80cc
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_template.json
@@ -0,0 +1,59 @@
+{
+ "server" : {
+ "boot_order" : "disk",
+ "core_number" : "1",
+ "firewall" : "off",
+ "hostname" : "localhost",
+ "ip_addresses" : {
+ "ip_address" : [
+ {
+ "access" : "private",
+ "address" : "10.1.3.163",
+ "family" : "IPv4"
+ },
+ {
+ "access" : "public",
+ "address" : "2a04:3540:1000:310:7cae:1dff:fead:3332",
+ "family" : "IPv6"
+ },
+ {
+ "access" : "public",
+ "address" : "94.237.37.216",
+ "family" : "IPv4",
+ "part_of_plan" : "yes"
+ }
+ ]
+ },
+ "license" : 0,
+ "memory_amount" : "1024",
+ "nic_model" : "virtio",
+ "password" : "777gznbm",
+ "plan" : "1xCPU-1GB",
+ "plan_ipv4_bytes" : "0",
+ "plan_ipv6_bytes" : "0",
+ "progress" : "0",
+ "state" : "maintenance",
+ "storage_devices" : {
+ "storage_device" : [
+ {
+ "address" : "virtio:0",
+ "storage" : "018e2c82-1c16-46b9-8b7d-aeaf8d8309a9",
+ "storage_size" : 10,
+ "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)",
+ "type" : "disk"
+ }
+ ]
+ },
+ "tags" : {
+ "tag" : []
+ },
+ "timezone" : "UTC",
+ "title" : "test_server",
+ "username" : "mlackman",
+ "uuid" : "00814aac-240f-4f08-9139-9697c9ffc0b7",
+ "video_model" : "cirrus",
+ "vnc" : "off",
+ "vnc_password" : "G4FvMjvg",
+ "zone" : "fi-hel1"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_cdrom.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_cdrom.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_cdrom.json
new file mode 100644
index 0000000..5f45a2b
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_cdrom.json
@@ -0,0 +1,411 @@
+{
+ "storages" : {
+ "storage" : [
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Standard (CD 1)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Standard (CD 2)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010010102"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Standard (CD 1)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010010201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Standard (CD 2)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010010202"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Enterprise (CD 1)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010020101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Enterprise (CD 2)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010020102"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Enterprise (CD 1)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010020201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Enterprise (CD 2)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010020202"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 3,
+ "state" : "online",
+ "title" : "Windows Server 2008 R2 Datacenter",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010030101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Datacenter",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010040101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Windows Server 2003 R2 Datacenter",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010040201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 4,
+ "state" : "online",
+ "title" : "Windows Server 2012",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000010050101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 5,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (DVD)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (netinst)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020010201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (netinst)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020010301"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (live)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020010401"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (live)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020010501"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 7.8 (Wheezy)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020020201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 8.6.0 (Jessie)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020030101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 9.0.0 (Stretch) Installation CD",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000020040101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Ubuntu Server 10.04",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000030010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Ubuntu Server 10.04",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000030010201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Ubuntu Server 11.04",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000030020101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Ubuntu Server 11.04",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000030020201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Ubuntu Server 12.04",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000030030101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Ubuntu Server 14.04 LTS",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000030040101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Ubuntu Server 16.04 LTS (Xenial Xerus), 64-bit",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000030060101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 4,
+ "state" : "online",
+ "title" : "Fedora 16 (DVD)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000040010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Fedora 16 (live)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000040010201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Fedora 19",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000040020101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 4,
+ "state" : "online",
+ "title" : "CentOS 6.0 (DVD 1)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000050010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "CentOS 6.0 (DVD 2)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000050010102"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 4,
+ "state" : "online",
+ "title" : "CentOS 6.8 (DVD 1)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000050010103"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 3,
+ "state" : "online",
+ "title" : "CentOS 6.8 (DVD 2)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000050010104"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 4,
+ "state" : "online",
+ "title" : "CentOS 6.8 (DVD 1)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000050010105"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "CentOS 6.8 (DVD 2)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000050010106"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 5,
+ "state" : "online",
+ "title" : "CentOS 7.3-1611 DVD",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000050010301"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 4,
+ "state" : "online",
+ "title" : "Knoppix 6.4.4",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000060010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Arch Linux 2010.05",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000070010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "CoreOS 607.0.0",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000080010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "CoreOS 845.0.0",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000080010201"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "CoreOS Alpha (1032.1.0)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000080010501"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "CoreOS Stable (1068.8.0)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000080020101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "Gentoo Linux Minimal Installation CD (64bit)",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000090010101"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 1,
+ "state" : "online",
+ "title" : "FreeBSD 11.0-RELEASE amd64 Installation CD",
+ "type" : "cdrom",
+ "uuid" : "01000000-0000-4000-8000-000100010101"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_template.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_template.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_template.json
new file mode 100644
index 0000000..12f42c2
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_template.json
@@ -0,0 +1,114 @@
+{
+ "storages" : {
+ "storage" : [
+ {
+ "access" : "public",
+ "license" : 3.36,
+ "size" : 20,
+ "state" : "online",
+ "title" : "Windows Server 2012 R2 Datacenter",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000010050200"
+ },
+ {
+ "access" : "public",
+ "license" : 0.694,
+ "size" : 20,
+ "state" : "online",
+ "title" : "Windows Server 2012 R2 Standard",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000010050300"
+ },
+ {
+ "access" : "public",
+ "license" : 3.36,
+ "size" : 20,
+ "state" : "online",
+ "title" : "Windows Server 2016 Datacenter",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000010060200"
+ },
+ {
+ "access" : "public",
+ "license" : 0.694,
+ "size" : 20,
+ "state" : "online",
+ "title" : "Windows Server 2016 Standard",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000010060300"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 7.8 (Wheezy)",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000020020100"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "Debian GNU/Linux 8.7 (Jessie)",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000020030100"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "Ubuntu Server 12.04 LTS (Precise Pangolin)",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000030030200"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "Ubuntu Server 14.04 LTS (Trusty Tahr)",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000030040200"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000030060200"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "CentOS 6.9",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000050010200"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 2,
+ "state" : "online",
+ "title" : "CentOS 7.0",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000050010300"
+ },
+ {
+ "access" : "public",
+ "license" : 0,
+ "size" : 5,
+ "state" : "online",
+ "title" : "CoreOS Stable 1068.8.0",
+ "type" : "template",
+ "uuid" : "01000000-0000-4000-8000-000080010200"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_zone.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_zone.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_zone.json
new file mode 100644
index 0000000..19deb8d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_zone.json
@@ -0,0 +1,30 @@
+{
+ "zones" : {
+ "zone" : [
+ {
+ "description" : "Frankfurt #1",
+ "id" : "de-fra1"
+ },
+ {
+ "description" : "Helsinki #1",
+ "id" : "fi-hel1"
+ },
+ {
+ "description" : "Amsterdam #1",
+ "id" : "nl-ams1"
+ },
+ {
+ "description" : "Singapore #1",
+ "id" : "sg-sin1"
+ },
+ {
+ "description" : "London #1",
+ "id" : "uk-lon1"
+ },
+ {
+ "description" : "Chicago #1",
+ "id" : "us-chi1"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/fixtures/upcloud/api_1_2_zone_failed_auth.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_zone_failed_auth.json b/libcloud/test/compute/fixtures/upcloud/api_1_2_zone_failed_auth.json
new file mode 100644
index 0000000..356841c
--- /dev/null
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_zone_failed_auth.json
@@ -0,0 +1,6 @@
+{
+ "error" : {
+ "error_code" : "AUTHENTICATION_FAILED",
+ "error_message" : "Authentication failed using the given username and password."
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/compute/test_upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_upcloud.py b/libcloud/test/compute/test_upcloud.py
new file mode 100644
index 0000000..41d02a0
--- /dev/null
+++ b/libcloud/test/compute/test_upcloud.py
@@ -0,0 +1,248 @@
+# 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.
+
+from __future__ import with_statement
+import sys
+import re
+import json
+import base64
+
+from libcloud.utils.py3 import httplib, ensure_string
+from libcloud.compute.drivers.upcloud import UpcloudDriver
+from libcloud.common.types import InvalidCredsError
+from libcloud.compute.drivers.upcloud import UpcloudResponse
+from libcloud.compute.types import NodeState
+from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, NodeAuthSSHKey, Node
+from libcloud.test import LibcloudTestCase, unittest, MockHttp
+from libcloud.test.file_fixtures import ComputeFileFixtures
+from libcloud.test.secrets import UPCLOUD_PARAMS
+
+
+class UpcloudPersistResponse(UpcloudResponse):
+
+ def parse_body(self):
+ import os
+ path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.pardir, 'compute', 'fixtures', 'upcloud'))
+ filename = 'api' + self.request.path_url.replace('/', '_').replace('.', '_') + '.json'
+ filename = os.path.join(path, filename)
+ if not os.path.exists(filename):
+ with open(filename, 'w+') as f:
+ f.write(self.body)
+ return super(UpcloudPersistResponse, self).parse_body()
+
+
+class UpcloudAuthenticationTests(LibcloudTestCase):
+
+ def setUp(self):
+ UpcloudDriver.connectionCls.conn_class = UpcloudMockHttp
+ self.driver = UpcloudDriver("nosuchuser", "nopwd")
+
+ def test_authentication_fails(self):
+ with self.assertRaises(InvalidCredsError):
+ self.driver.list_locations()
+
+
+class UpcloudDriverTests(LibcloudTestCase):
+
+ def setUp(self):
+ UpcloudDriver.connectionCls.conn_class = UpcloudMockHttp
+ # UpcloudDriver.connectionCls.responseCls = UpcloudPersistResponse
+ self.driver = UpcloudDriver(*UPCLOUD_PARAMS)
+
+ def test_features(self):
+ features = self.driver.features['create_node']
+ self.assertIn('ssh_key', features)
+ self.assertIn('generates_password', features)
+
+ def test_list_locations(self):
+ locations = self.driver.list_locations()
+ self.assertTrue(len(locations) >= 1)
+ expected_node_location = NodeLocation(id='fi-hel1',
+ name='Helsinki #1',
+ country='FI',
+ driver=self.driver)
+ self.assert_object(expected_node_location, objects=locations)
+
+ def test_list_sizes(self):
+ sizes = self.driver.list_sizes()
+ self.assertTrue(len(sizes) >= 1)
+ expected_node_size = NodeSize(id='1xCPU-1GB',
+ name='1xCPU-1GB',
+ ram=1024,
+ disk=30,
+ bandwidth=2048,
+ price=None,
+ driver=self.driver,
+ extra={'core_number': 1,
+ 'storage_tier': 'maxiops'})
+ self.assert_object(expected_node_size, objects=sizes)
+
+ def test_list_images(self):
+ images = self.driver.list_images()
+ self.assertTrue(len(images) >= 1)
+ expected_node_image = NodeImage(id='01000000-0000-4000-8000-000010010101',
+ name='Windows Server 2003 R2 Standard (CD 1)',
+ driver=self.driver,
+ extra={'access': 'public',
+ 'licence': 0,
+ 'size': 1,
+ 'state': 'online',
+ 'type': 'cdrom'})
+ self.assert_object(expected_node_image, objects=images)
+
+ def test_create_node_from_template(self):
+ image = NodeImage(id='01000000-0000-4000-8000-000030060200',
+ name='Ubuntu Server 16.04 LTS (Xenial Xerus)',
+ extra={'type': 'template'},
+ driver=self.driver)
+ location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver=self.driver)
+ size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048,
+ extra={'core_number': 1, 'storage_tier': 'maxiops'}, price=None, driver=self.driver)
+ node = self.driver.create_node(name='test_server', size=size, image=image, location=location)
+
+ self.assertTrue(re.match('^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$', node.id))
+ self.assertEquals(node.name, 'test_server')
+ self.assertEquals(node.state, NodeState.STARTING)
+ self.assertTrue(len(node.public_ips) > 0)
+ self.assertTrue(len(node.private_ips) > 0)
+ self.assertEquals(node.driver, self.driver)
+ self.assertTrue(len(node.extra['password']) > 0)
+ self.assertTrue(len(node.extra['vnc_password']) > 0)
+
+ def test_create_node_with_ssh_keys(self):
+ image = NodeImage(id='01000000-0000-4000-8000-000030060200',
+ name='Ubuntu Server 16.04 LTS (Xenial Xerus)',
+ extra={'type': 'template'},
+ driver=self.driver)
+ location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver=self.driver)
+ size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048,
+ extra={'core_number': 1, 'storage_tier': 'maxiops'}, price=None, driver=self.driver)
+
+ auth = NodeAuthSSHKey('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCUUFfYA+T+BzoM7IIR' +
+ 'VXNndDjYvIROMjfyRBhhHf6RZd1IkAwcWSGISePh2tIiqu8gJalYYHg2w' +
+ 'i3ofMJfi6VYeyBFWrIDhMK0v+ziBbBUtlJNnP6MBOR/13avkk+76TVrcG' +
+ 'xu49RaptYNzZ21XluvIlaqqdjAhoh0J+o7OZTKD7N1UTPL7CIX+ITaA+g' +
+ '3FR5ITClk8KmIbp3vT6fUPD7pNUrGBZTpcPcHq8rodQ8igWIVdSkb9iky' +
+ 'ew4y6wvsubQ3Ykn26XeKxrk1vA6ZKMHt7ijCYmfL0LcDfctNymy/vc6hs' +
+ 'WxCRS5OqNQ6nxdXpv9A+TD0sJuf5jaoH7MSpU1 mika.lackman@gmail.com')
+ node = self.driver.create_node(name='test_server', size=size, image=image, location=location, auth=auth)
+ self.assertTrue(re.match('^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$', node.id))
+ self.assertEquals(node.name, 'test_server')
+ self.assertEquals(node.state, NodeState.STARTING)
+ self.assertTrue(len(node.public_ips) > 0)
+ self.assertTrue(len(node.private_ips) > 0)
+ self.assertEquals(node.driver, self.driver)
+
+ def test_list_nodes(self):
+ nodes = self.driver.list_nodes()
+
+ self.assertTrue(len(nodes) >= 1)
+ node = nodes[0]
+ self.assertEquals(node.name, 'test_server')
+ self.assertEquals(node.state, NodeState.RUNNING)
+ self.assertTrue(len(node.public_ips) > 0)
+ self.assertTrue(len(node.private_ips) > 0)
+ self.assertEquals(node.driver, self.driver)
+
+ def test_reboot_node(self):
+ nodes = self.driver.list_nodes()
+ success = self.driver.reboot_node(nodes[0])
+ self.assertTrue(success)
+
+ def test_destroy_node(self):
+ if UpcloudDriver.connectionCls.conn_class == UpcloudMockHttp:
+ nodes = [Node(id='00893c98_5d5a_4363_b177_88df518a2b60', name='', state='',
+ public_ips=[], private_ips=[], driver=self.driver)]
+ else:
+ nodes = self.driver.list_nodes()
+ success = self.driver.destroy_node(nodes[0])
+ self.assertTrue(success)
+
+ def assert_object(self, expected_object, objects):
+ same_data = any([self.objects_equals(expected_object, obj) for obj in objects])
+ self.assertTrue(same_data, "Objects does not match")
+
+ def objects_equals(self, expected_obj, obj):
+ for name in vars(expected_obj):
+ expected_data = getattr(expected_obj, name)
+ actual_data = getattr(obj, name)
+ same_data = self.data_equals(expected_data, actual_data)
+ if not same_data:
+ break
+ return same_data
+
+ def data_equals(self, expected_data, actual_data):
+ if isinstance(expected_data, dict):
+ return self.dicts_equals(expected_data, actual_data)
+ else:
+ return expected_data == actual_data
+
+ def dicts_equals(self, d1, d2):
+ """Assumes dicts to contain only hashable types"""
+ return set(d1.values()) == set(d2.values())
+
+
+class UpcloudMockHttp(MockHttp):
+ fixtures = ComputeFileFixtures('upcloud')
+
+ def _1_2_zone(self, method, url, body, headers):
+ auth = headers['Authorization'].split(' ')[1]
+ username, password = ensure_string(base64.b64decode(auth)).split(':')
+ if username == 'nosuchuser' and password == 'nopwd':
+ body = self.fixtures.load('api_1_2_zone_failed_auth.json')
+ status_code = httplib.UNAUTHORIZED
+ else:
+ body = self.fixtures.load('api_1_2_zone.json')
+ status_code = httplib.OK
+ return (status_code, body, {}, httplib.responses[httplib.OK])
+
+ def _1_2_plan(self, method, url, body, headers):
+ body = self.fixtures.load('api_1_2_plan.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _1_2_storage_cdrom(self, method, url, body, headers):
+ body = self.fixtures.load('api_1_2_storage_cdrom.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _1_2_storage_template(self, method, url, body, headers):
+ body = self.fixtures.load('api_1_2_storage_template.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _1_2_server(self, method, url, body, headers):
+ if method == 'POST':
+ dbody = json.loads(body)
+ storages = dbody['server']['storage_devices']['storage_device']
+ if any(['type' in storage and storage['type'] == 'cdrom' for storage in storages]):
+ body = self.fixtures.load('api_1_2_server_from_cdrom.json')
+ else:
+ body = self.fixtures.load('api_1_2_server_from_template.json')
+ else:
+ body = self.fixtures.load('api_1_2_server.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _1_2_server_00f8c525_7e62_4108_8115_3958df5b43dc(self, method, url, body, headers):
+ body = self.fixtures.load('api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _1_2_server_00f8c525_7e62_4108_8115_3958df5b43dc_restart(self, method, url, body, headers):
+ body = self.fixtures.load('api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _1_2_server_00893c98_5d5a_4363_b177_88df518a2b60(self, method, url, body, headers):
+ body = self.fixtures.load('api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+if __name__ == '__main__':
+ sys.exit(unittest.main())
http://git-wip-us.apache.org/repos/asf/libcloud/blob/abbd9bb6/libcloud/test/secrets.py-dist
----------------------------------------------------------------------
diff --git a/libcloud/test/secrets.py-dist b/libcloud/test/secrets.py-dist
index 1b30bf2..8eaa0c6 100644
--- a/libcloud/test/secrets.py-dist
+++ b/libcloud/test/secrets.py-dist
@@ -57,6 +57,7 @@ VULTR_PARAMS = ('key')
PACKET_PARAMS = ('api_key')
ECS_PARAMS = ('access_key', 'access_secret')
CLOUDSCALE_PARAMS = ('token',)
+UPCLOUD_PARAMS = ('user', 'secret')
# Storage
STORAGE_S3_PARAMS = ('key', 'secret')
[07/14] libcloud git commit: Docstrings added for public classes
Posted by qu...@apache.org.
Docstrings added for public classes
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/82b5c3cc
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/82b5c3cc
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/82b5c3cc
Branch: refs/heads/trunk
Commit: 82b5c3cc63e28d7a540974f7bfeb832e4c68d16c
Parents: d238e93
Author: Mika Lackman <mi...@upcloud.com>
Authored: Sun Sep 24 16:08:31 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/common/upcloud.py | 67 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 66 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/82b5c3cc/libcloud/common/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/common/upcloud.py b/libcloud/common/upcloud.py
index cbb2904..a63be08 100644
--- a/libcloud/common/upcloud.py
+++ b/libcloud/common/upcloud.py
@@ -27,6 +27,27 @@ class UpcloudCreateNodeRequestBody(object):
Body of the create_node request
Takes the create_node arguments (**kwargs) and constructs the request body
+
+ :param user_id: required for authentication (required)
+ :type user_id: ``str``
+
+ :param name: Name of the created server (required)
+ :type name: ``str``
+
+ :param size: The size of resources allocated to this node.
+ :type size: :class:`.NodeSize`
+
+ :param image: OS Image to boot on node.
+ :type image: :class:`.NodeImage`
+
+ :param location: Which data center to create a node in. If empty,
+ undefined behavior will be selected. (optional)
+ :type location: :class:`.NodeLocation`
+
+ :param auth: Initial authentication information for the node
+ (optional)
+ :type auth: :class:`.NodeAuthSSHKey`
+
"""
def __init__(self, user_id, name, size, image, location, auth=None):
@@ -44,15 +65,26 @@ class UpcloudCreateNodeRequestBody(object):
def to_json(self):
"""
Serializes the body to json
+
+ :return: JSON string
+ :rtype: ``str``
"""
return json.dumps(self.body)
class UpcloudNodeDestroyer(object):
"""
- Destroyes the node.
+ Helper class for destroying node.
Node must be first stopped and then it can be
destroyed
+
+ :param upcloud_node_operations: UpcloudNodeOperations instance
+ :type upcloud_node_operations: :class:`.UpcloudNodeOperations`
+
+ :param sleep_func: Callable function, which sleeps.
+ Takes int argument to sleep in seconds (optional)
+ :type sleep_func: ``function``
+
"""
WAIT_AMOUNT = 2
@@ -64,6 +96,12 @@ class UpcloudNodeDestroyer(object):
self._sleep_count = 0
def destroy_node(self, node_id):
+ """
+ Destroys the given node.
+
+ :param node_id: Id of the Node.
+ :type node_id: ``int``
+ """
self._stop_called = False
self._sleep_count = 0
return self._do_destroy_node(node_id)
@@ -99,11 +137,23 @@ class UpcloudNodeDestroyer(object):
class UpcloudNodeOperations(object):
+ """
+ Helper class to start and stop node.
+
+ :param conneciton: Connection instance
+ :type connection: :class:`.UpcloudConnection`
+ """
def __init__(self, connection):
self.connection = connection
def stop_node(self, node_id):
+ """
+ Stops the node
+
+ :param node_id: Id of the Node
+ :type node_id: ``int``
+ """
body = {
'stop_server': {
'stop_type': 'hard'
@@ -114,6 +164,15 @@ class UpcloudNodeOperations(object):
data=json.dumps(body))
def node_state(self, node_id):
+ """
+ Get the state of the node.
+
+ :param node_id: Id of the Node
+ :type node_id: ``int``
+
+ :rtype: ``str``
+ """
+
action = '1.2/server/{0}'.format(node_id)
try:
response = self.connection.request(action)
@@ -124,6 +183,12 @@ class UpcloudNodeOperations(object):
raise
def destroy_node(self, node_id):
+ """
+ Destroys the node.
+
+ :param node_id: Id of the Node
+ :type node_id: ``int``
+ """
self.connection.request('1.2/server/{0}'.format(node_id),
method='DELETE')
[05/14] libcloud git commit: New compute driver for UpCloud
Posted by qu...@apache.org.
New compute driver for UpCloud
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/33c1e6fd
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/33c1e6fd
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/33c1e6fd
Branch: refs/heads/trunk
Commit: 33c1e6fdbbb6ceefc9be933ebfe555930a0a02d2
Parents: abbd9bb
Author: Mika Lackman <mi...@upcloud.com>
Authored: Mon Aug 14 14:03:29 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/test/compute/test_upcloud.py | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/33c1e6fd/libcloud/test/compute/test_upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_upcloud.py b/libcloud/test/compute/test_upcloud.py
index 41d02a0..98e0105 100644
--- a/libcloud/test/compute/test_upcloud.py
+++ b/libcloud/test/compute/test_upcloud.py
@@ -130,13 +130,7 @@ class UpcloudDriverTests(LibcloudTestCase):
size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048,
extra={'core_number': 1, 'storage_tier': 'maxiops'}, price=None, driver=self.driver)
- auth = NodeAuthSSHKey('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCUUFfYA+T+BzoM7IIR' +
- 'VXNndDjYvIROMjfyRBhhHf6RZd1IkAwcWSGISePh2tIiqu8gJalYYHg2w' +
- 'i3ofMJfi6VYeyBFWrIDhMK0v+ziBbBUtlJNnP6MBOR/13avkk+76TVrcG' +
- 'xu49RaptYNzZ21XluvIlaqqdjAhoh0J+o7OZTKD7N1UTPL7CIX+ITaA+g' +
- '3FR5ITClk8KmIbp3vT6fUPD7pNUrGBZTpcPcHq8rodQ8igWIVdSkb9iky' +
- 'ew4y6wvsubQ3Ykn26XeKxrk1vA6ZKMHt7ijCYmfL0LcDfctNymy/vc6hs' +
- 'WxCRS5OqNQ6nxdXpv9A+TD0sJuf5jaoH7MSpU1 mika.lackman@gmail.com')
+ auth = NodeAuthSSHKey('publikey')
node = self.driver.create_node(name='test_server', size=size, image=image, location=location, auth=auth)
self.assertTrue(re.match('^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$', node.id))
self.assertEquals(node.name, 'test_server')
[08/14] libcloud git commit: inherit exception from LibcloudError
Posted by qu...@apache.org.
inherit exception from LibcloudError
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/5326c9aa
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/5326c9aa
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/5326c9aa
Branch: refs/heads/trunk
Commit: 5326c9aa938c35fd773d27d2d53c9e5e21d3658f
Parents: 82b5c3c
Author: Mika Lackman <mi...@upcloud.com>
Authored: Sun Sep 24 19:38:38 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/common/upcloud.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/5326c9aa/libcloud/common/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/common/upcloud.py b/libcloud/common/upcloud.py
index a63be08..02413fc 100644
--- a/libcloud/common/upcloud.py
+++ b/libcloud/common/upcloud.py
@@ -16,9 +16,10 @@ import json
import time
from libcloud.common.exceptions import BaseHTTPError
+from libcloud.common.types import LibcloudError
-class UpcloudTimeoutException(Exception):
+class UpcloudTimeoutException(LibcloudError):
pass
[02/14] libcloud git commit: renamed method from node_state to
get_node_state
Posted by qu...@apache.org.
renamed method from node_state to get_node_state
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/513b9110
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/513b9110
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/513b9110
Branch: refs/heads/trunk
Commit: 513b9110bf62946695f0a0a8b817c32e4ba12cbc
Parents: e7df948
Author: Mika Lackman <mi...@upcloud.com>
Authored: Tue Sep 26 16:34:20 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/common/upcloud.py | 4 ++--
libcloud/test/common/test_upcloud.py | 18 +++++++++---------
2 files changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/513b9110/libcloud/common/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/common/upcloud.py b/libcloud/common/upcloud.py
index 02413fc..b824664 100644
--- a/libcloud/common/upcloud.py
+++ b/libcloud/common/upcloud.py
@@ -108,7 +108,7 @@ class UpcloudNodeDestroyer(object):
return self._do_destroy_node(node_id)
def _do_destroy_node(self, node_id):
- state = self._operations.node_state(node_id)
+ state = self._operations.get_node_state(node_id)
if state == 'stopped':
self._operations.destroy_node(node_id)
return True
@@ -164,7 +164,7 @@ class UpcloudNodeOperations(object):
method='POST',
data=json.dumps(body))
- def node_state(self, node_id):
+ def get_node_state(self, node_id):
"""
Get the state of the node.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/513b9110/libcloud/test/common/test_upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_upcloud.py b/libcloud/test/common/test_upcloud.py
index 76dd9c1..2df8213 100644
--- a/libcloud/test/common/test_upcloud.py
+++ b/libcloud/test/common/test_upcloud.py
@@ -142,7 +142,7 @@ class TestUpcloudNodeDestroyer(unittest.TestCase):
self.destroyer = UpcloudNodeDestroyer(self.mock_operations, sleep_func=self.mock_sleep)
def test_node_already_in_stopped_state(self):
- self.mock_operations.node_state.side_effect = ['stopped']
+ self.mock_operations.get_node_state.side_effect = ['stopped']
self.assertTrue(self.destroyer.destroy_node(1))
@@ -150,7 +150,7 @@ class TestUpcloudNodeDestroyer(unittest.TestCase):
self.mock_operations.destroy_node.assert_called_once_with(1)
def test_node_in_error_state(self):
- self.mock_operations.node_state.side_effect = ['error']
+ self.mock_operations.get_node_state.side_effect = ['error']
self.assertFalse(self.destroyer.destroy_node(1))
@@ -158,7 +158,7 @@ class TestUpcloudNodeDestroyer(unittest.TestCase):
self.assertTrue(self.mock_operations.destroy_node.call_count == 0)
def test_node_in_started_state(self):
- self.mock_operations.node_state.side_effect = ['started', 'stopped']
+ self.mock_operations.get_node_state.side_effect = ['started', 'stopped']
self.assertTrue(self.destroyer.destroy_node(1))
@@ -166,7 +166,7 @@ class TestUpcloudNodeDestroyer(unittest.TestCase):
self.mock_operations.destroy_node.assert_called_once_with(1)
def test_node_in_maintenace_state(self):
- self.mock_operations.node_state.side_effect = ['maintenance', 'maintenance', None]
+ self.mock_operations.get_node_state.side_effect = ['maintenance', 'maintenance', None]
self.assertTrue(self.destroyer.destroy_node(1))
@@ -176,7 +176,7 @@ class TestUpcloudNodeDestroyer(unittest.TestCase):
self.assertTrue(self.mock_operations.destroy_node.call_count == 0)
def test_node_statys_in_started_state_for_awhile(self):
- self.mock_operations.node_state.side_effect = ['started', 'started', 'stopped']
+ self.mock_operations.get_node_state.side_effect = ['started', 'started', 'stopped']
self.assertTrue(self.destroyer.destroy_node(1))
@@ -187,7 +187,7 @@ class TestUpcloudNodeDestroyer(unittest.TestCase):
def test_reuse(self):
"Verify that internal flag self.destroyer._stop_node is handled properly"
- self.mock_operations.node_state.side_effect = ['started', 'stopped', 'started', 'stopped']
+ 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))
@@ -195,16 +195,16 @@ class TestUpcloudNodeDestroyer(unittest.TestCase):
self.assertEquals(self.mock_operations.stop_node.call_count, 2)
def test_timeout(self):
- self.mock_operations.node_state.side_effect = ['maintenance'] * 50
+ 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.node_state.side_effect = ['maintenance'] * 50
+ self.mock_operations.get_node_state.side_effect = ['maintenance'] * 50
self.assertRaises(UpcloudTimeoutException, self.destroyer.destroy_node, 1)
- self.mock_operations.node_state.side_effect = ['maintenance', None]
+ self.mock_operations.get_node_state.side_effect = ['maintenance', None]
self.assertTrue(self.destroyer.destroy_node(1))
[06/14] libcloud git commit: fixing docstring line handling
Posted by qu...@apache.org.
fixing docstring line handling
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d238e939
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d238e939
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d238e939
Branch: refs/heads/trunk
Commit: d238e9391cad3d94e50d6e35b9d4efe06f598cda
Parents: 33c1e6f
Author: Mika Lackman <mi...@upcloud.com>
Authored: Sun Sep 24 08:45:06 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
libcloud/common/upcloud.py | 14 ++++++++++----
libcloud/compute/drivers/upcloud.py | 17 +++++++++++++----
2 files changed, 23 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d238e939/libcloud/common/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/common/upcloud.py b/libcloud/common/upcloud.py
index 432606a..cbb2904 100644
--- a/libcloud/common/upcloud.py
+++ b/libcloud/common/upcloud.py
@@ -23,10 +23,12 @@ class UpcloudTimeoutException(Exception):
class UpcloudCreateNodeRequestBody(object):
- """Body of the create_node request
+ """
+ Body of the create_node request
Takes the create_node arguments (**kwargs) and constructs the request body
"""
+
def __init__(self, user_id, name, size, image, location, auth=None):
self.body = {
'server': {
@@ -40,14 +42,18 @@ class UpcloudCreateNodeRequestBody(object):
}
def to_json(self):
- """Serializes the body to json"""
+ """
+ Serializes the body to json
+ """
return json.dumps(self.body)
class UpcloudNodeDestroyer(object):
- """Destroyes the node.
+ """
+ Destroyes the node.
Node must be first stopped and then it can be
- destroyed"""
+ destroyed
+ """
WAIT_AMOUNT = 2
SLEEP_COUNT_TO_TIMEOUT = 20
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d238e939/libcloud/compute/drivers/upcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/upcloud.py b/libcloud/compute/drivers/upcloud.py
index b9daf84..d2e0314 100644
--- a/libcloud/compute/drivers/upcloud.py
+++ b/libcloud/compute/drivers/upcloud.py
@@ -37,7 +37,9 @@ SERVER_STATE = {
class UpcloudResponse(JsonResponse):
- """Response class for UpcloudDriver"""
+ """
+ Response class for UpcloudDriver
+ """
def success(self):
if self.status == httplib.NO_CONTENT:
@@ -52,7 +54,10 @@ class UpcloudResponse(JsonResponse):
class UpcloudConnection(ConnectionUserAndKey):
- """Connection class for UpcloudDriver"""
+ """
+ Connection class for UpcloudDriver
+ """
+
host = 'api.upcloud.com'
responseCls = UpcloudResponse
@@ -71,7 +76,8 @@ class UpcloudConnection(ConnectionUserAndKey):
class UpcloudDriver(NodeDriver):
- """Upcloud node driver
+ """
+ Upcloud node driver
:keyword username: Username required for authentication
:type username: ``str``
@@ -79,6 +85,7 @@ class UpcloudDriver(NodeDriver):
:keyword password: Password required for authentication
:type password: ``str``
"""
+
type = Provider.UPCLOUD
name = 'Upcloud'
website = 'https://www.upcloud.com'
@@ -207,7 +214,9 @@ class UpcloudDriver(NodeDriver):
return destroyer.destroy_node(node.id)
def _node_ids(self):
- """Returns list of server uids currently on upcloud"""
+ """
+ Returns list of server uids currently on upcloud
+ """
response = self.connection.request('1.2/server')
servers = response.object['servers']['server']
return [server['uuid'] for server in servers]
[11/14] libcloud git commit: Created upcloud.rst
Posted by qu...@apache.org.
Created upcloud.rst
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/9a97e3b9
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/9a97e3b9
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/9a97e3b9
Branch: refs/heads/trunk
Commit: 9a97e3b9e22bef0852aaed2061328db3c9797913
Parents: 0e0b683
Author: Ilari Mäkelä <il...@users.noreply.github.com>
Authored: Mon Sep 25 16:44:34 2017 +0300
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
docs/compute/drivers/upcloud.rst | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/9a97e3b9/docs/compute/drivers/upcloud.rst
----------------------------------------------------------------------
diff --git a/docs/compute/drivers/upcloud.rst b/docs/compute/drivers/upcloud.rst
new file mode 100644
index 0000000..4c6a400
--- /dev/null
+++ b/docs/compute/drivers/upcloud.rst
@@ -0,0 +1,31 @@
+UpCloud Driver Documentation
+===============================
+`UpCloud`_ is a Finnish IaaS provider offering the most high performance
+servers with extremely redundant infrastructure to the most demanding customers.
+
+.. figure:: /_static/images/provider_logos/upcloud.png
+ :align: center
+ :width: 300
+ :target: https://www.upcloud.com/
+
+UpCloud currently operates globally from six (6) data centres:
+
+* Amsterdam, Netherlands
+* Chicago, USA
+* Frankfurt, Germany
+* Helsinki, Finland
+* London, UK
+* Singapore, Singapore
+
+Instantiating a driver
+----------------------
+
+When you instantiate a driver you need to pass the following arguments to the
+driver constructor:
+
+* ``username`` - Your API access enabled users username
+* ``password`` - Your API access enabled users password
+
+You can setup your API access enabled user account from https://my.upcloud.com/account
+
+.. _`UpCloud`: https://www.upcloud.com/
[13/14] libcloud git commit: docs: Fix upcloud.rst whitespace
Posted by qu...@apache.org.
docs: Fix upcloud.rst whitespace
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/f37b7c01
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/f37b7c01
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/f37b7c01
Branch: refs/heads/trunk
Commit: f37b7c01a6476dc5427e0a484cb5d427608455e5
Parents: 513b911
Author: Quentin Pradet <qu...@apache.org>
Authored: Wed Sep 27 06:50:54 2017 +0400
Committer: Quentin Pradet <qu...@apache.org>
Committed: Wed Sep 27 07:04:33 2017 +0400
----------------------------------------------------------------------
docs/compute/drivers/upcloud.rst | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f37b7c01/docs/compute/drivers/upcloud.rst
----------------------------------------------------------------------
diff --git a/docs/compute/drivers/upcloud.rst b/docs/compute/drivers/upcloud.rst
index 09ae874..e24b46c 100644
--- a/docs/compute/drivers/upcloud.rst
+++ b/docs/compute/drivers/upcloud.rst
@@ -1,6 +1,6 @@
UpCloud Driver Documentation
===============================
-`UpCloud`_ is a Finnish IaaS provider offering high performance servers
+`UpCloud`_ is a Finnish IaaS provider offering high performance servers
from data centers based in multiple countries.
.. figure:: /_static/images/provider_logos/upcloud.png
@@ -29,16 +29,16 @@ driver constructor:
Enabling API access
-------------------
-To allow API access to your UpCloud account, you first need to enable the API
-permissions by visiting `My Account -> User accounts`_ in your UpCloud Control
-Panel. We recommend you to set up a sub-account specifically for the API usage
-with its own username and password, as it allows you to assign specific permissions
+To allow API access to your UpCloud account, you first need to enable the API
+permissions by visiting `My Account -> User accounts`_ in your UpCloud Control
+Panel. We recommend you to set up a sub-account specifically for the API usage
+with its own username and password, as it allows you to assign specific permissions
for increased security.
-Click **Add user** and fill in the required details, and check the
-“**Allow API connections**” checkbox to enable API for the user. You can also
-limit the API connections to a specific IP address or address range for additional
-security. Once you are done entering the user information, hit the **Save** button
+Click **Add user** and fill in the required details, and check the
+“**Allow API connections**” checkbox to enable API for the user. You can also
+limit the API connections to a specific IP address or address range for additional
+security. Once you are done entering the user information, hit the **Save** button
at the bottom of the page to create the new username.
.. _`UpCloud`: https://www.upcloud.com/