Repository: libcloud
Updated Branches:
  refs/heads/trunk 6d2a3bbfe -> 72399b43b


Nodes now have a `created_at` attribute

* Base Node object has `created_at` which indicates the `datetime` the
  node was launched/started/created.
* EC2, Digital Ocean, OpenStack fill this attribute.
* Nodes at drivers that do not (yet) support it have `NoneType` as date.
* Document changes.

closes #698

[GITHUB-698]

Signed-off-by: Allard Hoeve <allardho...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/72399b43
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/72399b43
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/72399b43

Branch: refs/heads/trunk
Commit: 72399b43bc25a201c25a7525e4a1c98e790fbf9b
Parents: 6d2a3bb
Author: Allard Hoeve <allardho...@gmail.com>
Authored: Wed Feb 10 15:18:02 2016 +0100
Committer: Allard Hoeve <allardho...@gmail.com>
Committed: Fri Feb 12 09:49:20 2016 +0100

----------------------------------------------------------------------
 CHANGES.rst                                   |  5 +++++
 libcloud/compute/base.py                      |  6 +++++-
 libcloud/compute/drivers/digitalocean.py      |  4 +++-
 libcloud/compute/drivers/ec2.py               |  5 ++++-
 libcloud/compute/drivers/openstack.py         |  2 ++
 libcloud/test/compute/test_digitalocean_v1.py |  4 ++++
 libcloud/test/compute/test_digitalocean_v2.py |  7 +++++++
 libcloud/test/compute/test_ec2.py             | 20 ++++++++++++--------
 libcloud/test/compute/test_openstack.py       |  3 +++
 9 files changed, 45 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index a5d882e..3168cce 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -51,6 +51,11 @@ Compute
   (GITHUB-697)
   [Rick van de Loo]
 
+- Added `Node.create_at` which, on supported drivers, contains the datetime the
+  node was first started.
+  (GITHUB-698)
+  [Allard Hoeve]
+
 Storage
 ~~~~~~~
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/compute/base.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/base.py b/libcloud/compute/base.py
index 2b9b18a..b64dd31 100644
--- a/libcloud/compute/base.py
+++ b/libcloud/compute/base.py
@@ -167,7 +167,7 @@ class Node(UuidMixin):
     """
 
     def __init__(self, id, name, state, public_ips, private_ips,
-                 driver, size=None, image=None, extra=None):
+                 driver, size=None, image=None, extra=None, created_at=None):
         """
         :param id: Node ID.
         :type id: ``str``
@@ -193,6 +193,9 @@ class Node(UuidMixin):
         :param image: Image of this node. (optional)
         :type size: :class:`.NodeImage`
 
+        :param created_at: The datetime this node was created (optional)
+        :type created_at: :class: `datetime.datetime`
+
         :param extra: Optional provider specific attributes associated with
                       this node.
         :type extra: ``dict``
@@ -205,6 +208,7 @@ class Node(UuidMixin):
         self.private_ips = private_ips if private_ips else []
         self.driver = driver
         self.size = size
+        self.created_at = created_at
         self.image = image
         self.extra = extra or {}
         UuidMixin.__init__(self)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py 
b/libcloud/compute/drivers/digitalocean.py
index d0b3d7b..a390352 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -18,6 +18,7 @@ DigitalOcean Driver
 import json
 import warnings
 
+from libcloud.utils.iso8601 import parse_date
 from libcloud.utils.py3 import httplib
 
 from libcloud.common.digitalocean import DigitalOcean_v1_BaseDriver
@@ -551,6 +552,7 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
         else:
             state = NodeState.UNKNOWN
 
+        created = parse_date(data['created_at'])
         networks = data['networks']
         private_ips = []
         public_ips = []
@@ -568,7 +570,7 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
 
         node = Node(id=data['id'], name=data['name'], state=state,
                     public_ips=public_ips, private_ips=private_ips,
-                    driver=self, extra=extra)
+                    created_at=created, driver=self, extra=extra)
         return node
 
     def _to_image(self, data):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 1df3efd..8367a14 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -5390,6 +5390,8 @@ class BaseEC2NodeDriver(NodeDriver):
         except KeyError:
             state = NodeState.UNKNOWN
 
+        created = parse_date(findtext(element=element, xpath='launchTime',
+                             namespace=NAMESPACE))
         instance_id = findtext(element=element, xpath='instanceId',
                                namespace=NAMESPACE)
         public_ip = findtext(element=element, xpath='ipAddress',
@@ -5421,7 +5423,8 @@ class BaseEC2NodeDriver(NodeDriver):
 
         return Node(id=instance_id, name=name, state=state,
                     public_ips=public_ips, private_ips=private_ips,
-                    driver=self.connection.driver, extra=extra)
+                    driver=self.connection.driver, created_at=created,
+                    extra=extra)
 
     def _to_images(self, object):
         return [self._to_image(el) for el in object.findall(

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/compute/drivers/openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/openstack.py 
b/libcloud/compute/drivers/openstack.py
index 0fe5722..199a7af 100644
--- a/libcloud/compute/drivers/openstack.py
+++ b/libcloud/compute/drivers/openstack.py
@@ -2096,6 +2096,7 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
         image_id = image.get('id', None) if image else None
         config_drive = api_node.get("config_drive", False)
         volumes_attached = api_node.get('os-extended-volumes:volumes_attached')
+        created = parse_date(api_node["created"])
 
         return Node(
             id=api_node['id'],
@@ -2104,6 +2105,7 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
                                           NodeState.UNKNOWN),
             public_ips=public_ips,
             private_ips=private_ips,
+            created_at=created,
             driver=self,
             extra=dict(
                 hostId=api_node['hostId'],

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/test/compute/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v1.py 
b/libcloud/test/compute/test_digitalocean_v1.py
index 5719500..a09b1a8 100644
--- a/libcloud/test/compute/test_digitalocean_v1.py
+++ b/libcloud/test/compute/test_digitalocean_v1.py
@@ -88,6 +88,10 @@ class DigitalOcean_v1_Tests(LibcloudTestCase):
         self.assertEqual(nodes[0].extra['image_id'], 1601)
         self.assertEqual(nodes[0].extra['size_id'], 66)
 
+    def test_list_nodes_does_not_support_created_datetime(self):
+        nodes = self.driver.list_nodes()
+        self.assertIsNone(nodes[0].created_at)
+
     def test_create_node_invalid_size(self):
         image = NodeImage(id='invalid', name=None, driver=self.driver)
         size = self.driver.list_sizes()[0]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/test/compute/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v2.py 
b/libcloud/test/compute/test_digitalocean_v2.py
index a4a1b01..5f14b7c 100644
--- a/libcloud/test/compute/test_digitalocean_v2.py
+++ b/libcloud/test/compute/test_digitalocean_v2.py
@@ -15,6 +15,9 @@
 import sys
 import unittest
 
+from datetime import datetime
+from libcloud.utils.iso8601 import UTC
+
 try:
     import simplejson as json
 except ImportError:
@@ -87,6 +90,10 @@ class DigitalOcean_v2_Tests(LibcloudTestCase):
         self.assertEqual(nodes[0].extra['image']['id'], 6918990)
         self.assertEqual(nodes[0].extra['size_slug'], '512mb')
 
+    def test_list_nodes_fills_created_datetime(self):
+        nodes = self.driver.list_nodes()
+        self.assertEqual(nodes[0].created_at, datetime(2014, 11, 14, 16, 29, 
21, tzinfo=UTC))
+
     def test_create_node_invalid_size(self):
         image = NodeImage(id='invalid', name=None, driver=self.driver)
         size = self.driver.list_sizes()[0]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py 
b/libcloud/test/compute/test_ec2.py
index 243425c..4f1bbe1 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -217,8 +217,10 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
         self.assertEqual(node.id, 'i-4382922a')
         self.assertEqual(node.name, node.id)
         self.assertEqual(len(node.public_ips), 2)
-        self.assertEqual(node.extra['launch_time'],
-                         '2013-12-02T11:58:11.000Z')
+
+        self.assertEqual(node.extra['launch_time'], '2013-12-02T11:58:11.000Z')
+        self.assertEqual(node.created_at, datetime(2013, 12, 2, 11, 58, 11, 
tzinfo=UTC))
+
         self.assertTrue('instance_type' in node.extra)
         self.assertEqual(node.extra['availability'], 'us-east-1d')
         self.assertEqual(node.extra['key_name'], 'fauxkey')
@@ -243,12 +245,14 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
         self.assertEqual(ret_node2.extra['subnet_id'], 'subnet-5fd9d412')
         self.assertEqual(ret_node2.extra['vpc_id'], 'vpc-61dcd30e')
         self.assertEqual(ret_node2.extra['tags']['Group'], 'VPC Test')
-        self.assertEqual(ret_node1.extra['launch_time'],
-                         '2013-12-02T11:58:11.000Z')
-        self.assertTrue('instance_type' in ret_node1.extra)
-        self.assertEqual(ret_node2.extra['launch_time'],
-                         '2013-12-02T15:58:29.000Z')
-        self.assertTrue('instance_type' in ret_node2.extra)
+
+        self.assertEqual(ret_node1.extra['launch_time'], 
'2013-12-02T11:58:11.000Z')
+        self.assertEqual(ret_node1.created_at, datetime(2013, 12, 2, 11, 58, 
11, tzinfo=UTC))
+        self.assertEqual(ret_node2.extra['launch_time'], 
'2013-12-02T15:58:29.000Z')
+        self.assertEqual(ret_node2.created_at, datetime(2013, 12, 2, 15, 58, 
29, tzinfo=UTC))
+
+        self.assertIn('instance_type', ret_node1.extra)
+        self.assertIn('instance_type', ret_node2.extra)
 
     def test_ex_list_reserved_nodes(self):
         node = self.driver.ex_list_reserved_nodes()[0]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/72399b43/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_openstack.py 
b/libcloud/test/compute/test_openstack.py
index ef8d341..ee2469d 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -775,6 +775,9 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
         self.assertTrue(
             'fec0:4801:7808:52:16:3eff:fe60:187d' in node.private_ips)
 
+        # test creation date
+        self.assertEqual(node.created_at, datetime.datetime(2011, 10, 11, 0, 
51, 39, tzinfo=UTC))
+
         self.assertEqual(node.extra.get('flavorId'), '2')
         self.assertEqual(node.extra.get('imageId'), '7')
         self.assertEqual(node.extra.get('metadata'), {})

Reply via email to