Skip to content

Instantly share code, notes, and snippets.

@darkarnium
Last active March 7, 2018 11:11
Show Gist options
  • Save darkarnium/9193fd62219836c72617d64e47c408e9 to your computer and use it in GitHub Desktop.
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.
''' 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)
@darkarnium
Copy link
Author

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 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment