Repository: apache/libcloud

Issue:
Turn all States into string values instead of ints
@Kami

Luckily, most tests already used the constants. I found a couple sloppy drivers, especially the ProfitBricks driver, which uses NodeState for everything, including Volumes and Snapshots. Maybe we fix that, maybe we leave it. It doesn't really matter.



Discussion:

Resolving patch:
diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py
--- a/libcloud/compute/types.py
+++ b/libcloud/compute/types.py
@@ -35,7 +35,27 @@
 ]
 
 
-class Provider(object):
+class Type(object):
+    @classmethod
+    def tostring(cls, value):
+        """Return the string representation of the state object attribute
+        :param str value: the state object to turn into string
+        :return: the uppercase string that represents the state object
+        :rtype: str
+        """
+        return value.upper()
+
+    @classmethod
+    def fromstring(cls, value):
+        """Return the state object attribute that matches the string
+        :param str value: the string to look up
+        :return: the state object attribute that matches the string
+        :rtype: str
+        """
+        return getattr(cls, value.upper(), None)
+
+
+class Provider(Type):
     """
     Defines for each of the supported providers
 
@@ -189,7 +209,7 @@ class Provider(object):
 }
 
 
-class NodeState(object):
+class NodeState(Type):
     """
     Standard states for a node
 
@@ -204,56 +224,42 @@ class NodeState(object):
     :cvar PAUSED: Node is paused.
     :cvar UNKNOWN: Node state is unknown.
     """
-    RUNNING = 0
-    REBOOTING = 1
-    TERMINATED = 2
-    PENDING = 3
-    UNKNOWN = 4
-    STOPPED = 5
-    SUSPENDED = 6
-    ERROR = 7
-    PAUSED = 8
-
-    @classmethod
-    def tostring(cls, value):
-        values = cls.__dict__
-        values = dict([(key, string) for key, string in values.items() if
-                       not key.startswith('__')])
-
-        for item_key, item_value in values.items():
-            if value == item_value:
-                return item_key
-
-    @classmethod
-    def fromstring(cls, value):
-        return getattr(cls, value.upper(), None)
-
-
-class StorageVolumeState(object):
+    RUNNING = 'running'
+    REBOOTING = 'rebooting'
+    TERMINATED = 'terminated'
+    PENDING = 'pending'
+    UNKNOWN = 'unknown'
+    STOPPED = 'stopped'
+    SUSPENDED = 'suspended'
+    ERROR = 'error'
+    PAUSED = 'paused'
+
+
+class StorageVolumeState(Type):
     """
     Standard states of a StorageVolume
     """
-    AVAILABLE = "available"
-    ERROR = "error"
-    INUSE = "in_use"
-    CREATING = "creating"
-    DELETING = "deleting"
-    DELETED = "deleted"
-    BACKUP = "backup"
-    ATTACHING = "attaching"
-    UNKNOWN = "unknown"
-
-
-class VolumeSnapshotState(object):
+    AVAILABLE = 'available'
+    ERROR = 'error'
+    INUSE = 'inuse'
+    CREATING = 'creating'
+    DELETING = 'deleting'
+    DELETED = 'deleted'
+    BACKUP = 'backup'
+    ATTACHING = 'attaching'
+    UNKNOWN = 'unknown'
+
+
+class VolumeSnapshotState(Type):
     """
     Standard states of VolumeSnapshots
     """
-    AVAILABLE = 0
-    ERROR = 1
-    CREATING = 2
-    DELETING = 3
-    RESTORING = 4
-    UNKNOWN = 5
+    AVAILABLE = 'available'
+    ERROR = 'error'
+    CREATING = 'creating'
+    DELETING = 'deleting'
+    RESTORING = 'restoring'
+    UNKNOWN = 'unknown'
 
 
 class Architecture(object):


Test patch:
diff --git a/libcloud/test/compute/test_azure.py b/libcloud/test/compute/test_azure.py
--- a/libcloud/test/compute/test_azure.py
+++ b/libcloud/test/compute/test_azure.py
@@ -113,7 +113,7 @@ def test_list_nodes_returned_successfully(self):
         self.assertListEqual(img0.public_ips, ["191.235.135.62"])
         self.assertListEqual(img0.private_ips, ["100.92.66.69"])
         self.assertEqual(img0.size, None)
-        self.assertEqual(img0.state, 0)
+        self.assertEqual(img0.state, NodeState.RUNNING)
         self.assertTrue(isinstance(img0.extra, dict))
         extra = img0.extra
         self.assertEqual(extra["instance_size"], 'Small')
diff --git a/libcloud/test/compute/test_profitbricks.py b/libcloud/test/compute/test_profitbricks.py
--- a/libcloud/test/compute/test_profitbricks.py
+++ b/libcloud/test/compute/test_profitbricks.py
@@ -42,12 +42,12 @@ def test_list_nodes(self):
         node = nodes[0]
         self.assertEqual(node.id, "c8e57d7b-e731-46ad-a913-1828c0562246")
         self.assertEqual(node.name, "server001")
-        self.assertEqual(node.state, 0)
+        self.assertEqual(node.state, NodeState.RUNNING)
         self.assertEqual(node.public_ips, ['162.254.25.197'])
         self.assertEqual(node.private_ips, ['10.10.108.12', '10.13.198.11'])
         self.assertEqual(node.extra['datacenter_id'], "e1e8ec0d-b47f-4d39-a91b-6e885483c899")
         self.assertEqual(node.extra['datacenter_version'], "5")
-        self.assertEqual(node.extra['provisioning_state'], 0)
+        self.assertEqual(node.extra['provisioning_state'], NodeState.RUNNING)
         self.assertEqual(node.extra['creation_time'], "2014-07-14T20:52:20.839Z")
         self.assertEqual(node.extra['last_modification_time'], "2014-07-14T22:11:09.324Z")
         self.assertEqual(node.extra['os_type'], "LINUX")
@@ -121,7 +121,7 @@ def test_list_volumes(self):
         self.assertEqual(volume.name, "storage001")
         self.assertEqual(volume.size, 50)
         self.assertEqual(volume.extra['server_id'], "ebee7d83-912b-42f1-9b62-b953351a7e29")
-        self.assertEqual(volume.extra['provisioning_state'], 0)
+        self.assertEqual(volume.extra['provisioning_state'], NodeState.RUNNING)
         self.assertEqual(volume.extra['creation_time'], "2014-07-15T03:19:38.252Z")
         self.assertEqual(volume.extra['last_modification_time'], "2014-07-15T03:28:58.724Z")
         self.assertEqual(volume.extra['image_id'], "d2f627c4-0289-11e4-9f63-52540066fee9")
@@ -331,7 +331,7 @@ def test_ex_list_interfaces(self):
         interface = interfaces[0]
         self.assertEqual(interface.id, "6b38a4f3-b851-4614-9e3a-5ddff4727727")
         self.assertEqual(interface.name, "StackPointCloud")
-        self.assertEqual(interface.state, 0)
+        self.assertEqual(interface.state, NodeState.RUNNING)
         self.assertEqual(interface.extra['server_id'], "234f0cf9-1efc-4ade-b829-036456584116")
         self.assertEqual(interface.extra['lan_id'], '3')
         self.assertEqual(interface.extra['internet_access'], 'false')
@@ -376,7 +376,7 @@ def test_ex_describe_network_interface(self):
 
         self.assertEqual(describe.id, "f1c7a244-2fa6-44ee-8fb6-871f337683a3")
         self.assertEqual(describe.name, None)
-        self.assertEqual(describe.state, 0)
+        self.assertEqual(describe.state, NodeState.RUNNING)
         self.assertEqual(describe.extra['datacenter_id'], "a3a2e730-0dc3-47e6-bac6-4c056d5e2aee")
         self.assertEqual(describe.extra['datacenter_version'], "6")
         self.assertEqual(describe.extra['server_id'], "c09f4f31-336c-4ad2-9ec7-591778513408")
diff --git a/libcloud/test/compute/test_types.py b/libcloud/test/compute/test_types.py
new file mode 100644
--- /dev/null
+++ b/libcloud/test/compute/test_types.py
@@ -0,0 +1,70 @@
+from unittest import TestCase
+
+from libcloud.compute.types import Provider, NodeState, StorageVolumeState, \
+    VolumeSnapshotState, Type
+
+
+class TestType(Type):
+    INUSE = "inuse"
+
+
+class TestTestType(TestCase):
+    model = TestType
+    attribute = TestType.INUSE
+
+    def test_provider_tostring(self):
+        self.assertEqual(Provider.tostring(TestType.INUSE), "INUSE")
+
+    def test_provider_fromstring(self):
+        self.assertEqual(TestType.fromstring("inuse"), TestType.INUSE)
+
+    def test_provider_fromstring_caseinsensitive(self):
+        self.assertEqual(TestType.fromstring("INUSE"), TestType.INUSE)
+
+
+class TestProvider(TestCase):
+
+    def test_provider_tostring(self):
+        self.assertEqual(Provider.tostring(Provider.RACKSPACE), "RACKSPACE")
+
+    def test_provider_fromstring(self):
+        self.assertEqual(Provider.fromstring("rackspace"), Provider.RACKSPACE)
+
+
+class TestNodeState(TestCase):
+
+    def test_nodestate_tostring(self):
+        self.assertEqual(NodeState.tostring(NodeState.RUNNING), "RUNNING")
+
+    def test_nodestate_fromstring(self):
+        self.assertEqual(NodeState.fromstring("running"), NodeState.RUNNING)
+
+
+class TestStorageVolumeState(TestCase):
+
+    def test_storagevolumestate_tostring(self):
+        self.assertEqual(
+            StorageVolumeState.tostring(StorageVolumeState.AVAILABLE),
+            "AVAILABLE"
+        )
+
+    def test_storagevolumestate_fromstring(self):
+        self.assertEqual(
+            StorageVolumeState.fromstring("available"),
+            StorageVolumeState.AVAILABLE
+        )
+
+
+class TestVolumeSnapshotState(TestCase):
+
+    def test_volumesnapshotstate_tostring(self):
+        self.assertEqual(
+            VolumeSnapshotState.tostring(VolumeSnapshotState.AVAILABLE),
+            "AVAILABLE"
+        )
+
+    def test_volumesnapshotstate_fromstring(self):
+        self.assertEqual(
+            VolumeSnapshotState.fromstring("available"),
+            VolumeSnapshotState.AVAILABLE
+        )