You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by al...@apache.org on 2015/03/27 12:10:05 UTC
libcloud git commit: Add state to StorageVolume
Repository: libcloud
Updated Branches:
refs/heads/trunk b81ede37f -> 7845e08a9
Add state to StorageVolume
closes #476
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/7845e08a
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/7845e08a
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/7845e08a
Branch: refs/heads/trunk
Commit: 7845e08a9d35f2c37c468c43511cf9677fb863b9
Parents: b81ede3
Author: Allard Hoeve <al...@byte.nl>
Authored: Wed Mar 4 16:41:07 2015 +0100
Committer: Allard Hoeve <al...@byte.nl>
Committed: Fri Mar 27 12:08:20 2015 +0100
----------------------------------------------------------------------
CHANGES.rst | 12 ++++++++++
libcloud/compute/base.py | 12 ++++++++--
libcloud/compute/drivers/ec2.py | 20 ++++++++++++++++-
libcloud/compute/drivers/ibm_sce.py | 2 +-
libcloud/compute/drivers/openstack.py | 23 +++++++++++++++++++-
libcloud/compute/types.py | 15 +++++++++++++
.../compute/fixtures/ec2/describe_volumes.xml | 6 ++---
.../fixtures/openstack_v1.1/_os_volumes.json | 2 +-
libcloud/test/compute/test_base.py | 6 ++++-
libcloud/test/compute/test_ec2.py | 15 +++++++++----
libcloud/test/compute/test_openstack.py | 7 ++++--
11 files changed, 104 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index bd839d5..84e0c6b 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -20,6 +20,18 @@ Compute
(GITHUB-488, LIBCLOUD-682)
[Greg Hill]
+- StorageVolume objects now have an attribute `state` that holds a
+ state variable that is standardized state across drivers. Drivers that
+ currently support the `state` attribute are OpenStack and EC2.
+ StorageVolume objects returned by drivers that do not support the
+ attribute will have a `state` of `None`. When a provider returns a state
+ that is unknown to the driver, the state will be `UNKNOWN`. Please report
+ such states. A couple of drivers already put state fields in the `extra`
+ fields of StorageVolumes. These fields were kept for
+ backwards-compatibility and for reference.
+ (GITHUB-476)
+ [Allard Hoeve]
+
- StorageVolume objects on EC2 and OpenStack now have a key called snapshot_id
in their extra dicts containing the snapshot ID the volume was based on.
(GITHUB-479)
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/compute/base.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/base.py b/libcloud/compute/base.py
index d0c8399..4cfcf46 100644
--- a/libcloud/compute/base.py
+++ b/libcloud/compute/base.py
@@ -30,7 +30,8 @@ from libcloud.utils.py3 import b
import libcloud.compute.ssh
from libcloud.pricing import get_size_price
-from libcloud.compute.types import NodeState, DeploymentError
+from libcloud.compute.types import NodeState, StorageVolumeState,\
+ DeploymentError
from libcloud.compute.ssh import SSHClient
from libcloud.common.base import ConnectionKey
from libcloud.common.base import BaseDriver
@@ -68,6 +69,7 @@ __all__ = [
'NodeDriver',
'StorageVolume',
+ 'StorageVolumeState',
'VolumeSnapshot',
# Deprecated, moved to libcloud.utils.networking
@@ -460,7 +462,8 @@ class StorageVolume(UuidMixin):
A base StorageVolume class to derive from.
"""
- def __init__(self, id, name, size, driver, extra=None):
+ def __init__(self, id, name, size, driver,
+ state=None, extra=None):
"""
:param id: Storage volume ID.
:type id: ``str``
@@ -474,6 +477,10 @@ class StorageVolume(UuidMixin):
:param driver: Driver this image belongs to.
:type driver: :class:`.NodeDriver`
+ :param state: Optional state of the StorageVolume. If not
+ provided, will default to UNKNOWN.
+ :type state: :class:`.StorageVolumeState`
+
:param extra: Optional provider specific attributes.
:type extra: ``dict``
"""
@@ -482,6 +489,7 @@ class StorageVolume(UuidMixin):
self.size = size
self.driver = driver
self.extra = extra
+ self.state = state
UuidMixin.__init__(self)
def list_snapshots(self):
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index b43aa88..67a4d52 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -41,7 +41,8 @@ from libcloud.compute.providers import Provider
from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize
from libcloud.compute.base import NodeImage, StorageVolume, VolumeSnapshot
from libcloud.compute.base import KeyPair
-from libcloud.compute.types import NodeState, KeyPairDoesNotExistError
+from libcloud.compute.types import NodeState, KeyPairDoesNotExistError, \
+ StorageVolumeState
__all__ = [
'API_VERSION',
@@ -1996,6 +1997,17 @@ class BaseEC2NodeDriver(NodeDriver):
'terminated': NodeState.TERMINATED
}
+ # http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Volume.html
+ VOLUME_STATE_MAP = {
+ 'available': StorageVolumeState.AVAILABLE,
+ 'in-use': StorageVolumeState.INUSE,
+ 'error': StorageVolumeState.ERROR,
+ 'creating': StorageVolumeState.CREATING,
+ 'deleting': StorageVolumeState.DELETING,
+ 'deleted': StorageVolumeState.DELETED,
+ 'error_deleting': StorageVolumeState.ERROR
+ }
+
def list_nodes(self, ex_node_ids=None, ex_filters=None):
"""
List all nodes
@@ -4699,6 +4711,11 @@ class BaseEC2NodeDriver(NodeDriver):
volId = findtext(element=element, xpath='volumeId',
namespace=NAMESPACE)
size = findtext(element=element, xpath='size', namespace=NAMESPACE)
+ raw_state = findtext(element=element, xpath='status',
+ namespace=NAMESPACE)
+
+ state = self.VOLUME_STATE_MAP.get(raw_state,
+ StorageVolumeState.UNKNOWN)
# Get our tags
tags = self._get_resource_tags(element)
@@ -4717,6 +4734,7 @@ class BaseEC2NodeDriver(NodeDriver):
name=name,
size=int(size),
driver=self,
+ state=state,
extra=extra)
def _to_snapshots(self, response):
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/compute/drivers/ibm_sce.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ibm_sce.py b/libcloud/compute/drivers/ibm_sce.py
index bcf73b9..66cbec6 100644
--- a/libcloud/compute/drivers/ibm_sce.py
+++ b/libcloud/compute/drivers/ibm_sce.py
@@ -711,7 +711,7 @@ class IBMNodeDriver(NodeDriver):
object.findtext('Name'),
object.findtext('Size'),
self.connection.driver,
- extra)
+ extra=extra)
def _to_volume_offerings(self, object):
return [self._to_volume_offering(iType) for iType in
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/compute/drivers/openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/openstack.py b/libcloud/compute/drivers/openstack.py
index df32d2b..8e0dc9d 100644
--- a/libcloud/compute/drivers/openstack.py
+++ b/libcloud/compute/drivers/openstack.py
@@ -45,7 +45,7 @@ from libcloud.compute.base import NodeSize, NodeImage
from libcloud.compute.base import (NodeDriver, Node, NodeLocation,
StorageVolume, VolumeSnapshot)
from libcloud.compute.base import KeyPair
-from libcloud.compute.types import NodeState, Provider
+from libcloud.compute.types import NodeState, StorageVolumeState, Provider
from libcloud.pricing import get_size_price
from libcloud.utils.xml import findall
@@ -104,6 +104,21 @@ class OpenStackNodeDriver(NodeDriver, OpenStackDriverMixin):
'UNKNOWN': NodeState.UNKNOWN
}
+ # http://developer.openstack.org/api-ref-blockstorage-v2.html#volumes-v2
+ VOLUME_STATE_MAP = {
+ 'creating': StorageVolumeState.CREATING,
+ 'available': StorageVolumeState.AVAILABLE,
+ 'attaching': StorageVolumeState.ATTACHING,
+ 'in-use': StorageVolumeState.INUSE,
+ 'deleting': StorageVolumeState.DELETING,
+ 'error': StorageVolumeState.ERROR,
+ 'error_deleting': StorageVolumeState.ERROR,
+ 'backing-up': StorageVolumeState.BACKUP,
+ 'restoring-backup': StorageVolumeState.BACKUP,
+ 'error_restoring': StorageVolumeState.ERROR,
+ 'error_extending': StorageVolumeState.ERROR,
+ }
+
def __new__(cls, key, secret=None, secure=True, host=None, port=None,
api_version=DEFAULT_API_VERSION, **kwargs):
if cls is OpenStackNodeDriver:
@@ -2090,14 +2105,20 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
def _to_volume(self, api_node):
if 'volume' in api_node:
api_node = api_node['volume']
+
+ state = self.VOLUME_STATE_MAP.get(api_node['status'],
+ StorageVolumeState.UNKNOWN)
+
return StorageVolume(
id=api_node['id'],
name=api_node['displayName'],
size=api_node['size'],
+ state=state,
driver=self,
extra={
'description': api_node['displayDescription'],
'attachments': [att for att in api_node['attachments'] if att],
+ # TODO: remove in 1.18.0
'state': api_node.get('status', None),
'snapshot_id': api_node.get('snapshotId', None),
'location': api_node.get('availabilityZone', None),
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/compute/types.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py
index 0aeaf4b..e59a397 100644
--- a/libcloud/compute/types.py
+++ b/libcloud/compute/types.py
@@ -223,6 +223,21 @@ class NodeState(object):
return getattr(cls, value.upper(), None)
+class StorageVolumeState(object):
+ """
+ Standard states of a StorageVolume
+ """
+ AVAILABLE = 0
+ ERROR = 1
+ INUSE = 2
+ CREATING = 3
+ DELETING = 4
+ DELETED = 5
+ BACKUP = 6
+ ATTACHING = 7
+ UNKNOWN = 8
+
+
class Architecture(object):
"""
Image and size architectures.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/test/compute/fixtures/ec2/describe_volumes.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/describe_volumes.xml b/libcloud/test/compute/fixtures/ec2/describe_volumes.xml
index 5dde8e4..f3ab603 100644
--- a/libcloud/test/compute/fixtures/ec2/describe_volumes.xml
+++ b/libcloud/test/compute/fixtures/ec2/describe_volumes.xml
@@ -15,7 +15,7 @@
<size>11</size>
<snapshotId/>
<availabilityZone>us-east-1c</availabilityZone>
- <status>available</status>
+ <status>in-use</status>
<createTime>2013-10-08T19:36:49.000Z</createTime>
<attachmentSet/>
</item>
@@ -24,7 +24,7 @@
<size>8</size>
<snapshotId>snap-30d37269</snapshotId>
<availabilityZone>us-east-1d</availabilityZone>
- <status>in-use</status>
+ <status>some-unknown-status</status>
<createTime>2013-06-25T02:04:12.000Z</createTime>
<attachmentSet>
<item>
@@ -39,4 +39,4 @@
<volumeType>standard</volumeType>
</item>
</volumeSet>
-</DescribeVolumesResponse>
\ No newline at end of file
+</DescribeVolumesResponse>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json b/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json
index b0c1a32..4218845 100644
--- a/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json
+++ b/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json
@@ -32,7 +32,7 @@
"metadata": {},
"size": 50,
"snapshotId": "01f48111-7866-4cd2-986a-e92683c4a363",
- "status": "available",
+ "status": "some-unknown-state",
"volumeType": "None"
}
]
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/test/compute/test_base.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_base.py b/libcloud/test/compute/test_base.py
index 84edf95..5173cf9 100644
--- a/libcloud/test/compute/test_base.py
+++ b/libcloud/test/compute/test_base.py
@@ -18,8 +18,9 @@ import unittest
from libcloud.common.base import Response
from libcloud.common.base import Connection, ConnectionKey, ConnectionUserAndKey
from libcloud.common.types import LibcloudError
-from libcloud.compute.base import Node, NodeSize, NodeImage, NodeDriver
+from libcloud.compute.base import Node, NodeSize, NodeImage, NodeDriver, StorageVolume
from libcloud.compute.base import NodeAuthSSHKey, NodeAuthPassword
+from libcloud.compute.types import StorageVolumeState
from libcloud.test import MockResponse # pylint: disable-msg=E0611
@@ -41,6 +42,9 @@ class BaseTests(unittest.TestCase):
def test_base_node_image(self):
NodeImage(id=0, name=0, driver=FakeDriver())
+ def test_base_storage_volume(self):
+ StorageVolume(id="0", name="0", size=10, driver=FakeDriver(), state=StorageVolumeState.AVAILABLE)
+
def test_base_response(self):
Response(MockResponse(status=200, body='foo'), ConnectionKey('foo'))
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py
index f74fa94..9ad0a0b 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -39,7 +39,7 @@ from libcloud.compute.drivers.ec2 import ExEC2AvailabilityZone
from libcloud.compute.drivers.ec2 import EC2NetworkSubnet
from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation
from libcloud.compute.base import StorageVolume, VolumeSnapshot
-from libcloud.compute.types import KeyPairDoesNotExistError
+from libcloud.compute.types import KeyPairDoesNotExistError, StorageVolumeState
from libcloud.test import MockHttpTestCase, LibcloudTestCase
from libcloud.test.compute import TestCaseMixin
@@ -772,18 +772,21 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
self.assertEqual('vol-10ae5e2b', volumes[0].id)
self.assertEqual(1, volumes[0].size)
self.assertEqual('available', volumes[0].extra['state'])
+ self.assertEqual(StorageVolumeState.AVAILABLE, volumes[0].state)
self.assertEqual('vol-v24bfh75', volumes[1].id)
self.assertEqual(11, volumes[1].size)
- self.assertEqual('available', volumes[1].extra['state'])
self.assertIsNone(volumes[1].extra['snapshot_id'])
+ self.assertEqual('in-use', volumes[1].extra['state'])
+ self.assertEqual(StorageVolumeState.INUSE, volumes[1].state)
self.assertEqual('vol-b6c851ec', volumes[2].id)
self.assertEqual(8, volumes[2].size)
- self.assertEqual('in-use', volumes[2].extra['state'])
+ self.assertEqual('some-unknown-status', volumes[2].extra['state'])
self.assertEqual('i-d334b4b3', volumes[2].extra['instance_id'])
self.assertEqual('/dev/sda1', volumes[2].extra['device'])
self.assertEqual('snap-30d37269', volumes[2].extra['snapshot_id'])
+ self.assertEqual(StorageVolumeState.UNKNOWN, volumes[2].state)
def test_create_volume(self):
location = self.driver.list_locations()[0]
@@ -796,6 +799,7 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
def test_destroy_volume(self):
vol = StorageVolume(id='vol-4282672b', name='test',
+ state=StorageVolumeState.AVAILABLE,
size=10, driver=self.driver)
retValue = self.driver.destroy_volume(vol)
@@ -803,7 +807,8 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
def test_attach(self):
vol = StorageVolume(id='vol-4282672b', name='test',
- size=10, driver=self.driver)
+ size=10, state=StorageVolumeState.AVAILABLE,
+ driver=self.driver)
node = Node('i-4382922a', None, None, None, None, self.driver)
retValue = self.driver.attach_volume(node, vol, '/dev/sdh')
@@ -812,6 +817,7 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
def test_detach(self):
vol = StorageVolume(id='vol-4282672b', name='test',
+ state=StorageVolumeState.INUSE,
size=10, driver=self.driver)
retValue = self.driver.detach_volume(vol)
@@ -819,6 +825,7 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
def test_create_volume_snapshot(self):
vol = StorageVolume(id='vol-4282672b', name='test',
+ state=StorageVolumeState.AVAILABLE,
size=10, driver=self.driver)
snap = self.driver.create_volume_snapshot(
vol, 'Test snapshot')
http://git-wip-us.apache.org/repos/asf/libcloud/blob/7845e08a/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index f3524ec..08b2c20 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -34,7 +34,7 @@ from libcloud.utils.py3 import u
from libcloud.common.types import InvalidCredsError, MalformedResponseError, \
LibcloudError
-from libcloud.compute.types import Provider, KeyPairDoesNotExistError
+from libcloud.compute.types import Provider, KeyPairDoesNotExistError, StorageVolumeState
from libcloud.compute.providers import get_driver
from libcloud.compute.drivers.openstack import (
OpenStack_1_0_NodeDriver, OpenStack_1_0_Response,
@@ -794,6 +794,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
self.assertEqual('cd76a3a1-c4ce-40f6-9b9f-07a61508938d', volume.id)
self.assertEqual('test_volume_2', volume.name)
+ self.assertEqual(StorageVolumeState.AVAILABLE, volume.state)
self.assertEqual(2, volume.size)
self.assertEqual(volume.extra, {
'description': '',
@@ -811,15 +812,17 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
'created_at': '2013-06-24T11:20:13.000000',
})
+ # also test that unknown state resolves to StorageVolumeState.UNKNOWN
volume = volumes[1]
self.assertEqual('cfcec3bc-b736-4db5-9535-4c24112691b5', volume.id)
self.assertEqual('test_volume', volume.name)
self.assertEqual(50, volume.size)
+ self.assertEqual(StorageVolumeState.UNKNOWN, volume.state)
self.assertEqual(volume.extra, {
'description': 'some description',
'attachments': [],
'snapshot_id': '01f48111-7866-4cd2-986a-e92683c4a363',
- 'state': 'available',
+ 'state': 'some-unknown-state',
'location': 'nova',
'volume_type': 'None',
'metadata': {},