Last active
March 7, 2018 11:11
-
-
Save darkarnium/9193fd62219836c72617d64e47c408e9 to your computer and use it in GitHub Desktop.
Rough implementation of a data-source which uses vSphere / VMware VMX guestinfo for cloud-init.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' Provides a VMware VMX backed Data Source for Cloud-Init. ''' | |
import yaml | |
from time import sleep | |
from base64 import b64decode | |
from subprocess import check_output | |
from subprocess import CalledProcessError | |
from cloudinit import log as logging | |
from cloudinit import sources | |
from cloudinit import util | |
# Define how long to wait for a value to appear in VMX, and how often to | |
# wait between polls if it is not yet available. | |
VMX_TIMEOUT = 300 | |
VMX_INTERVAL = 10 | |
VMX_COMMAND = 'vmtoolsd' | |
LOG = logging.getLogger(__name__) | |
class DataSourceVMware(sources.DataSource): | |
''' Implements a VMware VMX backed data source. ''' | |
dsname = 'VMware' | |
def _get_vmx_value(self, key, command=VMX_COMMAND): | |
''' Attempt to get a given key from VMX using vmtoolsd. ''' | |
vmx_timer = 0 | |
while vmx_timer <= VMX_TIMEOUT: | |
try: | |
result = check_output( | |
[command, '--cmd', '"info-get guestinfo.{}"'.format(key)] | |
) | |
except CalledProcessError: | |
vmx_timer += VMX_INTERVAL | |
sleep(VMX_INTERVAL) | |
# If a result failed to be retrieved in the allotted time period, the | |
# following operation will raise a NameError. If it did return but was | |
# blank, just return a blank value. | |
try: | |
if result and not raw: | |
return b64decode(result) | |
else: | |
return result | |
except TypeError: | |
raise AttributeError( | |
'Decode failed, guestinfo.{} from VMX may be corrupt!'.format( | |
key | |
) | |
) | |
except NameError: | |
raise AttributeError( | |
'guestinfo.{} was unable to be read from VMX in time!'.format( | |
key | |
) | |
) | |
def get_data(self): | |
''' Attempt to pull data from VMX. ''' | |
LOG.debug('Attempting to get cloud-init userdata from VMX channel') | |
self.userdata_raw = self._get_vmx_value('userdata') | |
LOG.debug('Attempting to get cloud-init metadata from VMX channel') | |
self.metadata = yaml.load(self._get_vmx_value('metadata')) | |
LOG.debug('Attmpting to get cloud-init network config from VMX channel') | |
self._network_config = yaml.load(self.get_vmx_value('networkconfig')) | |
def get_instance_id(self): | |
''' Fetch the instance-id from the captured metadata. ''' | |
return self.metadata['instance-id'] | |
def get_hostname(self, fqdn=False): | |
''' Fetch the hostname from the captured metadata. ''' | |
if fqdn: | |
return self.metadata['hostname'] | |
else: | |
return self.metadata['hostname'].split('.')[0] | |
@property | |
def network_config(self): | |
''' Provides network configuration from the fetched data. ''' | |
return self._network_config | |
@property | |
def availability_zone(self): | |
''' Provides availability zone information from the fetched data. ''' | |
return None | |
@property | |
def region(self): | |
''' Provides region from information the fetched data. ''' | |
return None | |
datasources = [ | |
(DataSourceVMware, (sources.DEP_FILESYSTEM,)), | |
] | |
def get_datasource_list(depends): | |
return sources.list_from_depends(depends, datasources) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For what it's worth, this is a rough semi-working implementation. Everything needed to make this work is here, but it needs quite a bit of modification to drop into cloud-init and use for machine provisioning :)