def startvessel_ex(vesselname, prog_platform, argstring): # Convert the programming platform to lowercase to make # it case insensitive. prog_platform = prog_platform.lower() if vesselname not in vesseldict: raise BadRequest, "No such vessel" if vesseldict[vesselname]['status'] == 'Started': raise BadRequest("Vessel has already been started") if prog_platform not in prog_platform_dir.keys(): raise BadRequest("Programming language platform is not supported.") # remove any prior stop file so that we can start if os.path.exists(vesseldict[vesselname]['stopfilename']): os.remove(vesseldict[vesselname]['stopfilename']) for char in argstring: if char not in allowedchars: raise BadRequest("Character '"+char+"' not allowed in arguments") # I'm going to capture the status and timestamp and then check the see if # the timestamp is updated... oldstatus, oldtimestamp = statusstorage.read_status(vesseldict[vesselname]['statusfilename']) # Armon: this is required to fetch the networkrestrictions information from the configuration configuration = persist.restore_object("nodeman.cfg") # Armon: Generate the IP/Iface preferences if they exist ip_iface_preference_flags = [] ip_iface_preference_str = "" # Needed for Win Mobile # Only add the flags if everything necessary exists if 'networkrestrictions' in configuration and 'repy_restricted' in configuration['networkrestrictions'] \ and configuration['networkrestrictions']['repy_restricted'] and 'repy_user_preference' in configuration['networkrestrictions']: # Generate the preference list for (is_ip, value) in configuration['networkrestrictions']['repy_user_preference']: # Append the correct flag if is_ip: ip_iface_preference_flags.append("--ip") ip_iface_preference_str += "--ip " else: ip_iface_preference_flags.append("--iface") ip_iface_preference_str += "--iface " # Append the value ip_iface_preference_flags.append(value) ip_iface_preference_str += "'" + value + "' " # Check for the --nootherips flag if 'repy_nootherips' in configuration['networkrestrictions'] and configuration['networkrestrictions']['repy_nootherips']: # Append the flag ip_iface_preference_flags.append("--nootherips") ip_iface_preference_str += "--nootherips " # Find the location where the sandbox files is located. Location of repyV1, repyV2 etc. prog_platform_location = os.path.join(prog_platform_dir[prog_platform], "repy.py") # I use absolute paths so that repy can still find the files after it # changes directories... # Conrad: switched this to sequence-style Popen invocation so that spaces # in files work. Switched it back to absolute paths. command = [sys.executable, prog_platform_location] + ip_iface_preference_flags + [ "--logfile", os.path.abspath(vesseldict[vesselname]['logfilename']), "--stop", os.path.abspath(vesseldict[vesselname]['stopfilename']), "--status", os.path.abspath(vesseldict[vesselname]['statusfilename']), "--cwd", os.path.abspath(vesselname), "--servicelog", "--execinfo", os.path.abspath(vesseldict[vesselname]['resourcefilename'])] + argstring.split() portable_popen.Popen(command) starttime = nonportable.getruntime() # wait for 10 seconds for it to start (else return an error) while nonportable.getruntime()-starttime < 10: newstatus, newtimestamp = statusstorage.read_status(vesseldict[vesselname]['statusfilename']) # Great! The timestamp was updated... The new status is the result of # our work. Let's tell the user what happened... if newtimestamp != oldtimestamp and newstatus != None: break # sleep while busy waiting... time.sleep(.5) else: return "Did not start in a timely manner\nWarning" # We need to update the status in the table because the status thread might # not notice this before our next request... (else occasional failures on XP) nmstatusmonitor.update_status(vesseldict, vesselname, newstatus, newtimestamp) return newstatus+"\nSuccess"
def startvessel_ex(vesselname, prog_platform, argstring): # Convert the programming platform to lowercase to make # it case insensitive. prog_platform = prog_platform.lower() if vesselname not in vesseldict: raise BadRequest, "No such vessel" if vesseldict[vesselname]['status'] == 'Started': raise BadRequest("Vessel has already been started") if prog_platform not in prog_platform_dir.keys(): raise BadRequest("Programming language platform is not supported.") # remove any prior stop file so that we can start if os.path.exists(vesseldict[vesselname]['stopfilename']): os.remove(vesseldict[vesselname]['stopfilename']) for char in argstring: if char not in allowedchars: raise BadRequest("Character '" + char + "' not allowed in arguments") # I'm going to capture the status and timestamp and then check the see if # the timestamp is updated... oldstatus, oldtimestamp = statusstorage.read_status( vesseldict[vesselname]['statusfilename']) # Armon: this is required to fetch the networkrestrictions information from the configuration configuration = persist.restore_object("nodeman.cfg") # Armon: Generate the IP/Iface preferences if they exist ip_iface_preference_flags = [] ip_iface_preference_str = "" # Needed for Win Mobile # Only add the flags if everything necessary exists if 'networkrestrictions' in configuration and 'repy_restricted' in configuration['networkrestrictions'] \ and configuration['networkrestrictions']['repy_restricted'] and 'repy_user_preference' in configuration['networkrestrictions']: # Generate the preference list for (is_ip, value ) in configuration['networkrestrictions']['repy_user_preference']: # Append the correct flag if is_ip: ip_iface_preference_flags.append("--ip") ip_iface_preference_str += "--ip " else: ip_iface_preference_flags.append("--iface") ip_iface_preference_str += "--iface " # Append the value ip_iface_preference_flags.append(value) ip_iface_preference_str += "'" + value + "' " # Check for the --nootherips flag if 'repy_nootherips' in configuration[ 'networkrestrictions'] and configuration[ 'networkrestrictions']['repy_nootherips']: # Append the flag ip_iface_preference_flags.append("--nootherips") ip_iface_preference_str += "--nootherips " # Find the location where the sandbox files is located. Location of repyV1, repyV2 etc. prog_platform_location = os.path.join(prog_platform_dir[prog_platform], "repy.py") # I use absolute paths so that repy can still find the files after it # changes directories... # Conrad: switched this to sequence-style Popen invocation so that spaces # in files work. Switched it back to absolute paths. command = [ sys.executable, prog_platform_location ] + ip_iface_preference_flags + [ "--logfile", os.path.abspath(vesseldict[vesselname]['logfilename']), "--stop", os.path.abspath(vesseldict[vesselname]['stopfilename']), "--status", os.path.abspath(vesseldict[vesselname]['statusfilename']), "--cwd", os.path.abspath(vesselname), "--servicelog", "--execinfo", os.path.abspath(vesseldict[vesselname]['resourcefilename']) ] + argstring.split() portable_popen.Popen(command) starttime = nonportable.getruntime() # wait for 10 seconds for it to start (else return an error) while nonportable.getruntime() - starttime < 10: newstatus, newtimestamp = statusstorage.read_status( vesseldict[vesselname]['statusfilename']) # Great! The timestamp was updated... The new status is the result of # our work. Let's tell the user what happened... if newtimestamp != oldtimestamp and newstatus != None: break # sleep while busy waiting... time.sleep(.5) else: return "Did not start in a timely manner\nWarning" # We need to update the status in the table because the status thread might # not notice this before our next request... (else occasional failures on XP) nmstatusmonitor.update_status(vesseldict, vesselname, newstatus, newtimestamp) return newstatus + "\nSuccess"
def run(self): try: while True: # the race condition here is that they might delete something and I will # check it. This is okay. I'll end up getting a KeyError when trying # to update the dictionary (checked below) or look at the old entry. for vesselname in self.statusdict.keys()[:]: try: statusfilename = self.statusdict[vesselname]['statusfilename'] oldstatus = self.statusdict[vesselname]['status'] except KeyError: # race condition, this was removed in the meantime. continue # there should be a status file (assuming we've inited) try: status,timestamp = statusstorage.read_status(statusfilename) except IOError, e: # if the file exists, raise the exception since we don't know what # it is about. if e[0] != 2: raise # file not found. This means it is fresh... status = 'Fresh' timestamp = time.time() # Armon: Check if status is ThreadErr, this is a critical error condition # that requires lowering the global thread count, and reseting all vessels if status == "ThreadErr": # Check if this is the first time for this timestamp # Since the status file is not removed, this is necessary so that we do not # continuously trigger the error handling code if not timestamp in self.threadErrSet: # Add the timestamp self.threadErrSet.add(timestamp) # Call the error handling module nmthreadingerror.handle_threading_error(self.nmAPI) # The status has a timestamp in case the process is killed harshly and # needs to be restarted. This allows ordering of status reports staleness = time.time() - timestamp if staleness < 0: # time is running backwards, likely a NTP update (allow it)... # print "Time is running backwards by increment '"+str(staleness)+"', allowing this" newstatus = status elif staleness > updatebound: # stale? newstatus = oldstatus if oldstatus == 'Started': # BUG: What happens if we're wrong and it's alive? What do we do? # How do we detect and fix this safely? newstatus = 'Stale' # We set the timestamp so that our update happens in the table... timestamp = time.time() - updatebound else: # it seems to be okay. Use the given status newstatus = status update_status(self.statusdict, vesselname, newstatus, timestamp) time.sleep(self.sleeptime) except Exception,e: servicelogger.log_last_exception() raise e
def run(self): try: while True: # the race condition here is that they might delete something and I will # check it. This is okay. I'll end up getting a KeyError when trying # to update the dictionary (checked below) or look at the old entry. for vesselname in self.statusdict.keys()[:]: try: statusfilename = self.statusdict[vesselname][ 'statusfilename'] oldstatus = self.statusdict[vesselname]['status'] except KeyError: # race condition, this was removed in the meantime. continue # there should be a status file (assuming we've inited) try: status, timestamp = statusstorage.read_status( statusfilename) except IOError, e: # if the file exists, raise the exception since we don't know what # it is about. if e[0] != 2: raise # file not found. This means it is fresh... status = 'Fresh' timestamp = time.time() # Armon: Check if status is ThreadErr, this is a critical error condition # that requires lowering the global thread count, and reseting all vessels if status == "ThreadErr": # Check if this is the first time for this timestamp # Since the status file is not removed, this is necessary so that we do not # continuously trigger the error handling code if not timestamp in self.threadErrSet: # Add the timestamp self.threadErrSet.add(timestamp) # Call the error handling module nmthreadingerror.handle_threading_error(self.nmAPI) # The status has a timestamp in case the process is killed harshly and # needs to be restarted. This allows ordering of status reports staleness = time.time() - timestamp if staleness < 0: # time is running backwards, likely a NTP update (allow it)... # print "Time is running backwards by increment '"+str(staleness)+"', allowing this" newstatus = status elif staleness > updatebound: # stale? newstatus = oldstatus if oldstatus == 'Started': # BUG: What happens if we're wrong and it's alive? What do we do? # How do we detect and fix this safely? newstatus = 'Stale' # We set the timestamp so that our update happens in the table... timestamp = time.time() - updatebound else: # it seems to be okay. Use the given status newstatus = status update_status(self.statusdict, vesselname, newstatus, timestamp) time.sleep(self.sleeptime) except Exception, e: servicelogger.log_last_exception() raise e