示例#1
0
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"
示例#2
0
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
示例#4
0
    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