← Back to team overview

cloud-init-dev team mailing list archive

[Merge] lp:~enolfc/cloud-init/opennebula-b64-userdata into lp:cloud-init

 

Enol Fernández has proposed merging lp:~enolfc/cloud-init/opennebula-b64-userdata into lp:cloud-init.

Requested reviews:
  cloud init development team (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~enolfc/cloud-init/opennebula-b64-userdata/+merge/212646

This change adds the possibility to have base64 encoded userdata in OpenNebula source. 

OpenNebula uses a text file with shell variables for storing the configuration variables (including user provided data). Some user data may not be renderable into this format, so using base64 encoding alleviates the problem. This change considers that, by default, USERDATA variable contains a base64 encoded string with the user provided data. This behavior can be deactivated by defining the USERDATA_ENCODING variable to anything different to "base64" (similarly to the Azure data source). 

This feature is of special interest for resource providers with rOCCI-server front-end as the ones in EGI's Federated Cloud (https://wiki.egi.eu/wiki/Fedcloud-tf:Main)

Unit tests for the change are included.
-- 
https://code.launchpad.net/~enolfc/cloud-init/opennebula-b64-userdata/+merge/212646
Your team cloud init development team is requested to review the proposed merge of lp:~enolfc/cloud-init/opennebula-b64-userdata into lp:cloud-init.
=== modified file 'cloudinit/sources/DataSourceOpenNebula.py'
--- cloudinit/sources/DataSourceOpenNebula.py	2014-01-17 01:11:27 +0000
+++ cloudinit/sources/DataSourceOpenNebula.py	2014-03-25 15:42:10 +0000
@@ -4,11 +4,13 @@
 #    Copyright (C) 2012 Yahoo! Inc.
 #    Copyright (C) 2012-2013 CERIT Scientific Cloud
 #    Copyright (C) 2012-2013 OpenNebula.org
+#    Copyright (C) 2014 Consejo Superior de Investigaciones Cientificas
 #
 #    Author: Scott Moser <scott.moser@xxxxxxxxxxxxx>
 #    Author: Joshua Harlow <harlowja@xxxxxxxxxxxxx>
 #    Author: Vlastimil Holer <xholer@xxxxxxxxxxxx>
 #    Author: Javier Fontan <jfontan@xxxxxxxxxxxxxx>
+#    Author: Enol Fernandez <enolfc@xxxxxxxxxxxxxx>
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License version 3, as
@@ -22,6 +24,7 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import base64
 import os
 import pwd
 import re
@@ -417,6 +420,15 @@
     elif "USERDATA" in context:
         results['userdata'] = context["USERDATA"]
 
+    # b64decode user data if necessary (default)
+    if 'userdata' in results:
+        userdata_encoding = context.get('USERDATA_ENCODING', None)
+        if userdata_encoding in (None, "base64"):
+            try:
+                results['userdata'] = base64.b64decode(results['userdata'])
+            except TypeError:
+                LOG.warn("Failed base64 decoding of userdata")
+
     # generate static /etc/network/interfaces
     # only if there are any required context variables
     # http://opennebula.org/documentation:rel3.8:cong#network_configuration

=== modified file 'tests/unittests/test_datasource/test_opennebula.py'
--- tests/unittests/test_datasource/test_opennebula.py	2014-01-17 16:09:15 +0000
+++ tests/unittests/test_datasource/test_opennebula.py	2014-03-25 15:42:10 +0000
@@ -4,6 +4,7 @@
 from mocker import MockerTestCase
 from tests.unittests.helpers import populate_dir
 
+from base64 import b64encode
 import os
 import pwd
 
@@ -164,10 +165,30 @@
 
             public_keys.append(SSH_KEY % (c + 1,))
 
-    def test_user_data(self):
-        for k in ('USER_DATA', 'USERDATA'):
-            my_d = os.path.join(self.tmp, k)
-            populate_context_dir(my_d, {k: USER_DATA})
+    def test_user_data_plain(self):
+        for k in ('USER_DATA', 'USERDATA'):
+            my_d = os.path.join(self.tmp, k)
+            populate_context_dir(my_d, {k: USER_DATA,
+                                        'USERDATA_ENCODING': ''})
+            results = ds.read_context_disk_dir(my_d)
+
+            self.assertTrue('userdata' in results)
+            self.assertEqual(USER_DATA, results['userdata'])
+
+    def test_user_data_default_encoding(self):
+        for k in ('USER_DATA', 'USERDATA'):
+            my_d = os.path.join(self.tmp, k)
+            populate_context_dir(my_d, {k: b64encode(USER_DATA)})
+            results = ds.read_context_disk_dir(my_d)
+
+            self.assertTrue('userdata' in results)
+            self.assertEqual(USER_DATA, results['userdata'])
+
+    def test_user_data_base64_encoding(self):
+        for k in ('USER_DATA', 'USERDATA'):
+            my_d = os.path.join(self.tmp, k)
+            populate_context_dir(my_d, {k: b64encode(USER_DATA),
+                                        'USERDATA_ENCODING': 'base64'})
             results = ds.read_context_disk_dir(my_d)
 
             self.assertTrue('userdata' in results)


Follow ups