Updated clear value for guestinfo keys
This patch updates the behavior of clearing a key from the guestinfo
key-space. For example, if the "userdata" key is cleared then
"guestinfo.userdata" is set to "---" and "guestinfo.userdata.encoding"
is set to an empty string.
diff --git a/DataSourceVMwareGuestInfo.py b/DataSourceVMwareGuestInfo.py
index a1467ea..ab392be 100644
--- a/DataSourceVMwareGuestInfo.py
+++ b/DataSourceVMwareGuestInfo.py
@@ -40,6 +40,7 @@
NOVAL = "No value found"
VMWARE_RPCTOOL = find_executable("vmware-rpctool")
VMX_GUESTINFO = "VMX_GUESTINFO"
+GUESTINFO_EMPTY_YAML_VAL = "---"
class NetworkConfigError(Exception):
@@ -234,6 +235,39 @@
return raw_data
+def get_none_if_empty_val(val):
+ '''
+ get_none_if_empty_val returns None if the provided value, once stripped
+ of its trailing whitespace, is empty or equal to GUESTINFO_EMPTY_YAML_VAL.
+
+ The return value is always a string, regardless of whether the input is
+ a bytes class or a string.
+ '''
+
+ # If the provided value is a bytes class, convert it to a string to
+ # simplify the rest of this function's logic.
+ if isinstance(val, bytes):
+ val = val.decode()
+
+ val = val.rstrip()
+ if len(val) == 0 or val == GUESTINFO_EMPTY_YAML_VAL:
+ return None
+ return val
+
+
+def handle_returned_guestinfo_val(key, val):
+ '''
+ handle_returned_guestinfo_val returns the provided value if it is
+ not empty or set to GUESTINFO_EMPTY_YAML_VAL, otherwise None is
+ returned
+ '''
+ val = get_none_if_empty_val(val)
+ if val:
+ return val
+ LOG.debug("No value found for key %s", key)
+ return None
+
+
def get_guestinfo_value(key):
'''
Returns a guestinfo value for the specified key.
@@ -244,11 +278,7 @@
if data_access_method == VMX_GUESTINFO:
env_key = ("vmx.guestinfo." + key).upper().replace(".", "_", -1)
- val = os.environ.get(env_key, "")
- if val == "":
- LOG.debug("No value found for key %s", key)
- else:
- return val
+ return handle_returned_guestinfo_val(key, os.environ.get(env_key, ""))
if data_access_method == VMWARE_RPCTOOL:
try:
@@ -259,7 +289,7 @@
elif not stdout:
LOG.error("Failed to get guestinfo value for key %s", key)
else:
- return stdout.rstrip()
+ return handle_returned_guestinfo_val(key, stdout)
except util.ProcessExecutionError as error:
if error.stderr == NOVAL:
LOG.debug("No value found for key %s", key)
@@ -310,22 +340,21 @@
def clear_guestinfo_keys(keys):
'''
- clear_guestinfo_keys clears guestinfo of all of the keys in the given list
+ clear_guestinfo_keys clears guestinfo of all of the keys in the given list.
+ each key will have its value set to "---". Since the value is valid YAML,
+ cloud-init can still read it if it tries.
'''
if not keys:
return
+ if not type(keys) in (list, tuple):
+ keys = [keys]
for key in keys:
- clear_guestinfo_value(key)
- clear_guestinfo_value(key + ".encoding")
-
-
-def clear_guestinfo_value(key):
- '''
- clear_guestinfo_value sets the specified guestinfo key to an empty string
- '''
- LOG.info("clearing guestinfo.%s", key)
- if not set_guestinfo_value(key, ''):
- LOG.error("failed to clear guestinfo.%s", key)
+ LOG.info("clearing guestinfo.%s", key)
+ if not set_guestinfo_value(key, GUESTINFO_EMPTY_YAML_VAL):
+ LOG.error("failed to clear guestinfo.%s", key)
+ LOG.info("clearing guestinfo.%s.encoding", key)
+ if not set_guestinfo_value(key + ".encoding", ""):
+ LOG.error("failed to clear guestinfo.%s.encoding", key)
def guestinfo(key):