+ ### handle filename
+ # build the filename string
+ # check for permissions and concurrency
+ # returns the filename
+ def handle_filename (self, filename, nodename, suffix, arch):
+ # allow to set filename to None or any other empty value
+ if not filename: filename=''
+ filename = filename.replace ("%d",self.WORKDIR)
+ filename = filename.replace ("%n",nodename)
+ filename = filename.replace ("%s",suffix)
+ filename = filename.replace ("%p",self.api.config.PLC_NAME)
+ # let's be cautious
+ try: filename = filename.replace ("%f", self.nodefamily)
+ except: pass
+ try: filename = filename.replace ("%a", arch)
+ except: pass
+ try: filename = filename.replace ("%v",self.bootcd_version())
+ except: pass
+
+ ### Check filename location
+ if filename != '':
+ if 'admin' not in self.caller['roles']:
+ if ( filename.index(self.WORKDIR) != 0):
+ raise PLCInvalidArgument("File {} not under {}".format(filename, self.WORKDIR))
+
+ ### output should not exist (concurrent runs ..)
+ # numerous reports of issues with this policy
+ # looks like people sometime suspend/cancel their download
+ # and this leads to the old file sitting in there forever
+ # so, if the file is older than 5 minutes, we just trash
+ grace=5
+ if os.path.exists(filename) and (time.time()-os.path.getmtime(filename)) >= (grace*60):
+ os.unlink(filename)
+ if os.path.exists(filename):
+ raise PLCInvalidArgument(
+ "Resulting file {} already exists - please try again in {} minutes"\
+ .format(filename, grace))
+
+ ### we can now safely create the file,
+ ### either we are admin or under a controlled location
+ filedir=os.path.dirname(filename)
+ # dirname does not return "." for a local filename like its shell counterpart
+ if filedir:
+ if not os.path.exists(filedir):
+ try:
+ os.makedirs (filedir,0777)
+ except:
+ raise PLCPermissionDenied("Could not create dir {}".format(filedir))
+
+ return filename
+
+ def build_command(self, nodename, node_type, build_sh_spec, node_image, type, floppy_file):
+ """
+ returns a tuple
+ (*) build command to be run
+ (*) location of the log_file
+ """
+
+ command = ""
+
+ # regular node, make build's arguments
+ # and build the full command line to be called
+ if node_type not in [ 'regular', 'reservable' ]:
+ print >> log, "GetBootMedium.build_command: unexpected node_type {}".format(node_type)
+ return command, None
+
+ build_sh_options=""
+ if "cramfs" in build_sh_spec:
+ type += "_cramfs"
+ if "serial" in build_sh_spec:
+ build_sh_options += " -s {}".format(build_sh_spec['serial'])
+ if "variant" in build_sh_spec:
+ build_sh_options += " -V {}".format(build_sh_spec['variant'])
+
+ for karg in build_sh_spec['kargs']:
+ build_sh_options += ' -k "{}"'.format(karg)
+
+ import time
+ date = time.strftime('%Y-%m-%d-%H-%M', time.gmtime())
+ if not os.path.isdir(self.LOGDIR):
+ os.makedirs(self.LOGDIR)
+ log_file = "{}/{}-{}.log".format(self.LOGDIR, date, nodename)
+
+ command = '{} -f "{}" -o "{}" -t "{}" {} > {} 2>&1'\
+ .format(self.BOOTCDBUILD,
+ floppy_file,
+ node_image,
+ type,
+ build_sh_options,
+ log_file)
+
+ print >> log, "The build command line is {}".format(command)
+
+ return command, log_file
+