add 'cloud-boothook' type
if user data is of type text/cloud-boothook, or begins with #cloud-boothook, then assume it to be code to be executed. Boothooks are a very simple format. Basically, its a one line header ('#cloud-config\n') and then executable payload. The executable payload is written to a file, then that file is executed at the time it is read. The file is left in /var/lib/cloud/data/boothooks There is no "first-time-only" protection. If running only once is desired, the boothook must handle that itself.
This commit is contained in:
parent
22bb3adc5d
commit
99bbf6f217
@ -40,6 +40,7 @@ class DataSourceEc2(DataSource.DataSource):
|
|||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
try:
|
try:
|
||||||
|
cloudinit.log.info("looking at %s/user-data.raw" % self.cachedir)
|
||||||
udf = open(self.cachedir + "/user-data.raw")
|
udf = open(self.cachedir + "/user-data.raw")
|
||||||
self.userdata_raw = udf.read()
|
self.userdata_raw = udf.read()
|
||||||
udf.close()
|
udf.close()
|
||||||
@ -132,7 +133,7 @@ class DataSourceEc2(DataSource.DataSource):
|
|||||||
(time.strftime("%H:%M:%S"), x+1, sleeps, reason))
|
(time.strftime("%H:%M:%S"), x+1, sleeps, reason))
|
||||||
time.sleep(sleeptime)
|
time.sleep(sleeptime)
|
||||||
|
|
||||||
log.critical("giving up on md after %i seconds\n" %
|
cloudinit.log.critical("giving up on md after %i seconds\n" %
|
||||||
int(time.time()-starttime))
|
int(time.time()-starttime))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@ starts_with_mappings={
|
|||||||
'#!' : 'text/x-shellscript',
|
'#!' : 'text/x-shellscript',
|
||||||
'#cloud-config' : 'text/cloud-config',
|
'#cloud-config' : 'text/cloud-config',
|
||||||
'#upstart-job' : 'text/upstart-job',
|
'#upstart-job' : 'text/upstart-job',
|
||||||
'#part-handler' : 'text/part-handler'
|
'#part-handler' : 'text/part-handler',
|
||||||
|
'#cloud-boothook' : 'text/cloud-boothook'
|
||||||
}
|
}
|
||||||
|
|
||||||
# if 'str' is compressed return decompressed otherwise return it
|
# if 'str' is compressed return decompressed otherwise return it
|
||||||
|
@ -25,6 +25,7 @@ cachedir = datadir + '/cache'
|
|||||||
userdata_raw = datadir + '/user-data.txt'
|
userdata_raw = datadir + '/user-data.txt'
|
||||||
userdata = datadir + '/user-data.txt.i'
|
userdata = datadir + '/user-data.txt.i'
|
||||||
user_scripts_dir = datadir + "/scripts"
|
user_scripts_dir = datadir + "/scripts"
|
||||||
|
boothooks_dir = datadir + "/boothooks"
|
||||||
cloud_config = datadir + '/cloud-config.txt'
|
cloud_config = datadir + '/cloud-config.txt'
|
||||||
#cloud_config = '/tmp/cloud-config.txt'
|
#cloud_config = '/tmp/cloud-config.txt'
|
||||||
data_source_cache = cachedir + '/obj.pkl'
|
data_source_cache = cachedir + '/obj.pkl'
|
||||||
@ -174,7 +175,8 @@ class CloudInit:
|
|||||||
'text/x-shellscript' : self.handle_user_script,
|
'text/x-shellscript' : self.handle_user_script,
|
||||||
'text/cloud-config' : self.handle_cloud_config,
|
'text/cloud-config' : self.handle_cloud_config,
|
||||||
'text/upstart-job' : self.handle_upstart_job,
|
'text/upstart-job' : self.handle_upstart_job,
|
||||||
'text/part-handler' : self.handle_handler
|
'text/part-handler' : self.handle_handler,
|
||||||
|
'text/cloud-boothook' : self.handle_cloud_boothook
|
||||||
}
|
}
|
||||||
self.sysconfig=sysconfig
|
self.sysconfig=sysconfig
|
||||||
self.cfg=self.read_cfg()
|
self.cfg=self.read_cfg()
|
||||||
@ -412,6 +414,39 @@ class CloudInit:
|
|||||||
|
|
||||||
self.cloud_config_str+="\n#%s\n%s" % (filename,payload)
|
self.cloud_config_str+="\n#%s\n%s" % (filename,payload)
|
||||||
|
|
||||||
|
def handle_cloud_boothook(self,data,ctype,filename,payload):
|
||||||
|
if ctype == "__end__": return
|
||||||
|
if ctype == "__begin__": return
|
||||||
|
|
||||||
|
filename=filename.replace(os.sep,'_')
|
||||||
|
prefix="#cloud-boothooks"
|
||||||
|
dos=False
|
||||||
|
start = 0
|
||||||
|
if payload.startswith(prefix):
|
||||||
|
start = len(prefix)+1
|
||||||
|
if payload[start] == '\r':
|
||||||
|
start=start+1
|
||||||
|
dos = True
|
||||||
|
else:
|
||||||
|
if payload.find('\r\n',0,100) >= 0:
|
||||||
|
dos = True
|
||||||
|
|
||||||
|
if dos:
|
||||||
|
payload=payload[start:].replace('\r\n','\n')
|
||||||
|
elif start != 0:
|
||||||
|
payload=payload[start:]
|
||||||
|
|
||||||
|
filepath = "%s/%s" % (boothooks_dir,filename)
|
||||||
|
util.write_file(filepath, payload, 0700)
|
||||||
|
try:
|
||||||
|
ret = subprocess.check_call([filepath])
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
log.error("boothooks script %s returned %i" %
|
||||||
|
(filepath,e.returncode))
|
||||||
|
except Exception as e:
|
||||||
|
log.error("boothooks unknown exception %s when running %s" %
|
||||||
|
(e,filepath))
|
||||||
|
|
||||||
def get_public_ssh_keys(self):
|
def get_public_ssh_keys(self):
|
||||||
return(self.datasource.get_public_ssh_keys())
|
return(self.datasource.get_public_ssh_keys())
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ starts_with_mappings={
|
|||||||
'#!' : 'text/x-shellscript',
|
'#!' : 'text/x-shellscript',
|
||||||
'#cloud-config' : 'text/cloud-config',
|
'#cloud-config' : 'text/cloud-config',
|
||||||
'#upstart-job' : 'text/upstart-job',
|
'#upstart-job' : 'text/upstart-job',
|
||||||
'#part-handler' : 'text/part-handler'
|
'#part-handler' : 'text/part-handler',
|
||||||
|
'#cloud-boothook' : 'text/cloud-boothook'
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_type(fname,deftype):
|
def get_type(fname,deftype):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user