Example #1
0
    def __init__(self,
                 input,
                 output,
                 version=nxparser.base.parser.DEFAULT_VERSION,
                 program=DEFAULT_PROGRAM):
        """server_parser constructor

    Args:
      input: The file object to read parser input from.
      output: The file object to write the results to.
      version: The version string used to negotiate the protocol.
      program: The program name used in the protocol banner.
    """
        nxparser.base.parser.__init__(self,
                                      input,
                                      output,
                                      version=version,
                                      program=program)
        self.port = 0

        username = os.getenv('NX_TRUSTED_USER')

        if username:
            self.status = self.STATUS_LOGGEDIN
            self.username = username
        else:
            self.status = self.STATUS_CONNECTED

        commfd = os.getenv('NX_COMMFD')

        if commfd:
            self.nxnode_commfd = int(commfd)
            self.nxnode_rfile = os.fdopen(self.nxnode_commfd, 'r')
            self.nxnode_wfile = os.fdopen(self.nxnode_commfd, 'w')
            nxlog.log(nxlog.LOG_DEBUG, 'Got commfd %d\n' % self.nxnode_commfd)
Example #2
0
    def _nx_hello_handler(self, command):
        """Handle the hello NX command.

    'hello' is used to handshake the commandline session, and appears to
    support negotiation of the protocol version. We currently only
    accept versions which look like 3.x.x, matched using a regex.

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

        # Basic checking of the right status
        if self.status >= self.STATUS_LOGGEDIN:
            self.prompt(
                554, 'Error: the command \'hello\' cannot '
                'be called after login')
            return
        if len(command) < 5:
            nxlog.log(nxlog.LOG_DEBUG, 'Hello too short')
            return
        if not re.match('^3(\.[0-9]+(\.[0-9]+))', command[4]):
            nxlog.log(nxlog.LOG_DEBUG, 'Version too f****d')
            self.prompt(552, 'Protocol you requested is not supported')
            return
        # If the proffered version is the same as ours, or older..
        if self._diff_version(self.version, command[4]) < 1:
            accept_ver = self.version
        else:
            accept_ver = command[4]
        self.prompt(134, 'Accepted protocol: %s' % accept_ver)
def check_command_var(varname, defval):
  def is_valid(path):
    try:
      cmd = path.split()[0]
    except IndexError:
      # Can happen if path is None, or "" etc
      cmd = path
    return cmd is not None and os.path.isfile(cmd) and os.access(cmd, os.X_OK)

  global __conf_errors
  varval = conf.get(varname)

  if varval is not None: # Is there a value set already?
    if is_valid(varval):
      return True # Everything checks out.
    else:
      nxlog.log(nxlog.LOG_WARNING, "Invalid command variable %s: \"%s\"\n" %
          (varname, varval))

  if defval == "" or is_valid(defval):
    # Everything ok now, we assume it's blank if deliberately unset
    # (or if the command isn't available
    conf[varname] = defval
    return True
  else:
    nxlog.log(nxlog.LOG_ERR, "Invalid default command variable %s: \"%s\"\n" %
        (varname, defval))
    __conf_errors = True
    return False
Example #4
0
  def __set_vars(self, parameters):
    """Set instances parameters from key=value string list

    Args:
      parameters: A list of key=value strings
    """
    self.params = copy.deepcopy(default_params)

    # Read values from supplied set
    for pair in parameters.split('\n'):
      if not pair: continue
      name,val = pair.split('=', 1)
      if name not in default_params:
        nxlog.log(nxlog.LOG_ERR, "Invalid session parameter passed in: %s" % pair)
      else:
        self.params[name] = val

    if not self.params['id']:
      self.params['id'] = gen_uniq_id()
    # Always generate full_id
    self.params['full_id'] = "%(hostname)s-%(display)s-%(id)s" % self.params
    if not self.params['cookie']:
      self.params['cookie'] = gen_uniq_id()
    if not self.params['user']:
      self.params['user'] = pwd.getpwuid(os.getuid())[0]
    if not self.params['cache']:
      type = self.params['type']
      if type.startswith('unix-'):
        type = type.split('-', 1)[0]
      self.params['cache'] = "cache-%s" % type
Example #5
0
    def _write_opts(self):
      """Create the session's 'options' file

      The options file is a comma-delimited list of options that are read in
      by nxagent
      """

      try:
        opts_file = open(self.opts_file_path, 'w')
        opts = ['nx/nx', 'keyboard=%(keyboard)s' % self,
            'geometry=%(geometry)s' % self, 'client=%(client)s' % self,
            'cache=8M', 'images=32M', 'link=%(link)s' % self,
            'type=%(shorttype)s' % self, 'clipboard=both', 'composite=1',
            'cleanup=0', 'accept=127.0.0.1', 'product=Freenx-gpl', 'shmem=1',
            'backingstore=1', 'shpix=1', 'cookie=%s' % self.cookie,
            'id=%s' % self.full_id, 'strict=0']
        if self.type == 'unix-application':
          opts.append('application=%(application)s' % self)
        if self.fullscreen == '1':
          opts.append('fullscreen=%(fullscreen)s' % self)
        opts_file.write("%s:%d\n" % (",".join(opts), self.display))
        opts_file.close()
      except IOError, e:
        nxlog.log(nxlog.LOG_ERR, 'IOError when writing '
            'session options file: %s' % e)
Example #6
0
  def __init__(self, input, output, version=nxparser.base.parser.DEFAULT_VERSION,
               program=DEFAULT_PROGRAM):
    """server_parser constructor

    Args:
      input: The file object to read parser input from.
      output: The file object to write the results to.
      version: The version string used to negotiate the protocol.
      program: The program name used in the protocol banner.
    """
    nxparser.base.parser.__init__(self, input, output, version=version, program=program)
    self.port = 0

    username = os.getenv('NX_TRUSTED_USER')

    if username:
      self.status = self.STATUS_LOGGEDIN
      self.username = username
    else:
      self.status = self.STATUS_CONNECTED

    commfd = os.getenv('NX_COMMFD')

    if commfd:
      self.nxnode_commfd = int(commfd)
      self.nxnode_rfile = os.fdopen(self.nxnode_commfd, 'r')
      self.nxnode_wfile = os.fdopen(self.nxnode_commfd, 'w')
      nxlog.log(nxlog.LOG_DEBUG, 'Got commfd %d\n' % self.nxnode_commfd)
Example #7
0
def check_command_var(varname, defval):
    def is_valid(path):
        try:
            cmd = path.split()[0]
        except IndexError:
            # Can happen if path is None, or "" etc
            cmd = path
        return cmd is not None and os.path.isfile(cmd) and os.access(
            cmd, os.X_OK)

    global __conf_errors
    varval = conf.get(varname)

    if varval is not None:  # Is there a value set already?
        if is_valid(varval):
            return True  # Everything checks out.
        else:
            nxlog.log(
                nxlog.LOG_WARNING,
                "Invalid command variable %s: \"%s\"\n" % (varname, varval))

    if defval == "" or is_valid(defval):
        # Everything ok now, we assume it's blank if deliberately unset
        # (or if the command isn't available
        conf[varname] = defval
        return True
    else:
        nxlog.log(
            nxlog.LOG_ERR, "Invalid default command variable %s: \"%s\"\n" %
            (varname, defval))
        __conf_errors = True
        return False
Example #8
0
def check_dir_var(varname, defval):
    def is_valid(path):
        return path is not None and os.path.isdir(path)

    global __conf_errors
    varval = conf.get(varname)

    if varval is not None:  # Is there a value set already?
        if is_valid(varval):
            return True  # Everything checks out.
        else:
            nxlog.log(
                nxlog.LOG_WARNING,
                "Invalid directory variable %s: \"%s\"\n" % (varname, varval))

    if is_valid(defval):
        # Everything ok now
        conf[varname] = defval
        return True
    else:
        nxlog.log(
            nxlog.LOG_ERR, "Invalid default directory variable %s: \"%s\"\n" %
            (varname, defval))
        __conf_errors = True
        return False
Example #9
0
  def _nx_hello_handler(self, command):
    """Handle the hello NX command.

    'hello' is used to handshake the commandline session, and appears to
    support negotiation of the protocol version. We currently only
    accept versions which look like 3.x.x, matched using a regex.

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

    # Basic checking of the right status
    if self.status >= self.STATUS_LOGGEDIN:
      self.prompt(554, 'Error: the command \'hello\' cannot '
          'be called after login')
      return
    if len(command) < 5:
      nxlog.log(nxlog.LOG_DEBUG, 'Hello too short')
      return
    if not re.match('^3(\.[0-9]+(\.[0-9]+))', command[4]):
      nxlog.log(nxlog.LOG_DEBUG, 'Version too f****d')
      self.prompt(552, 'Protocol you requested is not supported')
      return
    # If the proffered version is the same as ours, or older..
    if self._diff_version(self.version, command[4]) < 1:
      accept_ver = self.version
    else:
      accept_ver = command[4]
    self.prompt(134, 'Accepted protocol: %s' % accept_ver)
Example #10
0
    def __set_vars(self, parameters):
        """Set instances parameters from key=value string list

    Args:
      parameters: A list of key=value strings
    """
        self.params = copy.deepcopy(default_params)

        # Read values from supplied set
        for pair in parameters.split("\n"):
            if not pair:
                continue
            name, val = pair.split("=", 1)
            if name not in default_params:
                nxlog.log(nxlog.LOG_ERR, "Invalid session parameter passed in: %s" % pair)
            else:
                self.params[name] = val

        if not self.params["id"]:
            self.params["id"] = gen_uniq_id()
        # Always generate full_id
        self.params["full_id"] = "%(hostname)s-%(display)s-%(id)s" % self.params
        if not self.params["cookie"]:
            self.params["cookie"] = gen_uniq_id()
        if not self.params["user"]:
            self.params["user"] = pwd.getpwuid(os.getuid())[0]
        if not self.params["cache"]:
            type = self.params["type"]
            if type.startswith("unix-"):
                type = type.split("-", 1)[0]
            self.params["cache"] = "cache-%s" % type
def __conf_load(conf_file):
  conf_file_path = os.path.join(conf["PATH_ETC"], "%s.conf" % conf_file)
  if not os.path.exists(conf_file_path):
    nxlog.log(nxlog.LOG_DEBUG, "Requested file %s doesn't exist\n" % conf_file_path)
    return
  for line in subprocess.Popen('nxloadconfig-helper.sh %s' % conf_file_path,
    shell=True, stdout=subprocess.PIPE, env=conf).stdout:
    var, val = line.split('=')
    conf[var] = val.rstrip()
Example #12
0
def __conf_load(conf_file):
    conf_file_path = os.path.join(conf["PATH_ETC"], "%s.conf" % conf_file)
    if not os.path.exists(conf_file_path):
        nxlog.log(nxlog.LOG_DEBUG,
                  "Requested file %s doesn't exist\n" % conf_file_path)
        return
    for line in subprocess.Popen('nxloadconfig-helper.sh %s' % conf_file_path,
                                 shell=True,
                                 stdout=subprocess.PIPE,
                                 env=conf).stdout:
        var, val = line.split('=')
        conf[var] = val.rstrip()
def setup(conf_file=None):
  global __conf_errors
  __conf_errors = False

  __conf_load("general")
  if conf_file: __conf_load(conf_file)
  __check_command_vars()
  __check_dir_vars()

  if __conf_errors:
    nxlog.log(nxlog.LOG_CRIT, "Configuration errors, exiting\n")
    sys.exit(1)
Example #14
0
def setup(conf_file=None):
    global __conf_errors
    __conf_errors = False

    __conf_load("general")
    if conf_file: __conf_load(conf_file)
    __check_command_vars()
    __check_dir_vars()

    if __conf_errors:
        nxlog.log(nxlog.LOG_CRIT, "Configuration errors, exiting\n")
        sys.exit(1)
Example #15
0
  def set_state(self, name):
    """Set the state of the session

    Does some sanity checking to make sure the new state is valid

    Args:
      name: Name of the state to set the session to.
    Returns:
      None
    """

    if name not in state_names:
      nxlog.log(nxlog.LOG_ERR, "Invalid state name passed in: %r" % name)
      # FIXME(diamond): handle error better
    else:
      self.params['state'] = name
Example #16
0
    def set_state(self, name):
        """Set the state of the session

    Does some sanity checking to make sure the new state is valid

    Args:
      name: Name of the state to set the session to.
    Returns:
      None
    """

        if name not in state_names:
            nxlog.log(nxlog.LOG_ERR, "Invalid state name passed in: %r" % name)
            # FIXME(diamond): handle error better
        else:
            self.params["state"] = name
Example #17
0
  def write(self, output, newline=True, flush=True, log=True,
      log_level=nxlog.LOG_DEBUG, fd=None):
    """Write given string to output, and optionally:
      - append a newline
      - flush output afterwards
      - log the output, with a specified log level."""

    if newline:
      output += '\n'
    use_fd = self.output
    if fd:
      use_fd = fd
    use_fd.write(output)
    if flush:
      use_fd.flush()
    if log:
      nxlog.log(log_level, 'Sent: %r\n' % output)
Example #18
0
  def __init__(self, input, output, version=DEFAULT_VERSION,
               program=DEFAULT_PROGRAM):
    """base_parser constructor

    Args:
      input: The file object to read parser input from.
      output: The file object to write the results to.
      version: The version string used to negotiate the protocol.
      program: The program name used in the protocol banner.
    """

    self.input = input
    self.output = output
    self.state = 105
    self.running = True
    self.parse_args(version=version, program=program)
    nxlog.log(nxlog.LOG_DEBUG, "Version: %s Program: %s" %
        (self.version, self.program))
Example #19
0
    def _write_args(self):
      """Create the session's 'args' file

      The args file is a newline-delimited list of arguments to be passed to
      nxagent
      """

      try:
        args_file = open(self.args_file_path, 'w')
        #DEBUG, FIXME(diamond):
        args_file.write("\n".join([self.mode, '-options', self.opts_file_path,
          '-name', 'FreeNX - %(user)s@%(hostname)s:%(display)s' % self,
          '-nolisten', 'tcp', ':%d' % self.display]))
        args_file.write("\n")
        args_file.close()
      except IOError, e:
        nxlog.log(nxlog.LOG_ERR, 'IOError when writing '
            'session args file: %s' % e)
Example #20
0
    def __del__(self):
        """Destructor for the server_parser class

    This is needed to cleanup after server_parser is done. In particular,
    the file descriptors used for comms with nxnode may be in an errored state
    if nxnode has exited.
    """

        for i in ['r', 'w']:
            var = "nxnode_%sfile" % i
            try:
                getattr(self, var).close()
            except IOError, e:
                if e.args[0] != errno.EBADF:
                    nxlog.log(nxlog.LOG_WARNING,
                              "Got error closing %s: %s\n" % (var, e))
            except AttributeError:
                pass  # self.nxnode_(r|w)file doesn't exist
Example #21
0
  def __del__(self):
    """Destructor for the server_parser class

    This is needed to cleanup after server_parser is done. In particular,
    the file descriptors used for comms with nxnode may be in an errored state
    if nxnode has exited.
    """

    for i in ['r', 'w']:
      var = "nxnode_%sfile" % i
      try:
        getattr(self, var).close()
      except IOError, e:
        if e.args[0] != errno.EBADF:
          nxlog.log(nxlog.LOG_WARNING, "Got error closing %s: %s\n" %
              (var, e))
      except AttributeError:
        pass # self.nxnode_(r|w)file doesn't exist
Example #22
0
    def _parse_param(self, param):
        """Check that param is correctly formatted via the NX_PARAM_RX regex

        Args:
          param: parameter string to be checked, of the form --key="value"

        Returns:
          key,value tuple if param was correctly formatted, returns None,None
          otherwise.
        """

        m = self.NX_PARAM_RX.search(param)
        if m:
            key = m.group('key')
            value = m.group('value')
            nxlog.log(nxlog.LOG_DEBUG, 'Param matched: %r=%r' % (key, value))
        else:
            key = value = None
            nxlog.log(nxlog.LOG_WARNING, "Param didn't match: %r" % param)
        return key, value
Example #23
0
  def _parse_param(self, param):
    """Check that param is correctly formatted via the NX_PARAM_RX regex

    Args:
      param: parameter string to be checked, of the form --key="value"

    Returns:
      key,value tuple if param was correctly formatted, returns None,None
      otherwise.
    """

    m = self.NX_PARAM_RX.search(param)
    if m:
      key = m.group('key')
      value = m.group('value')
      nxlog.log(nxlog.LOG_DEBUG, 'Param matched: %r=%r' % (key, value))
    else:
      key = value = None
      nxlog.log(nxlog.LOG_WARNING, "Param didn't match: %r" % param)
    return key,value
Example #24
0
    def __init__(self,
                 input,
                 output,
                 version=DEFAULT_VERSION,
                 program=DEFAULT_PROGRAM):
        """base_parser constructor

        Args:
          input: The file object to read parser input from.
          output: The file object to write the results to.
          version: The version string used to negotiate the protocol.
          program: The program name used in the protocol banner.
        """

        self.input = input
        self.output = output
        self.state = 105
        self.running = True
        self.parse_args(version=version, program=program)
        nxlog.log(nxlog.LOG_DEBUG,
                  "Version: %s Program: %s" % (self.version, self.program))
Example #25
0
    def daemonize(self):
        """Drop into the background."""

        # I am assumuing this throws if fork fails.
        pid = os.fork()
        # In the parent, return.
        if pid != 0:
            # self.nxnode_rfile.close()
            # self.nxnode_wfile.close()
            os.close(self.nxnode_commfd)
            # del(self.nxnode_rfile)
            # del(self.nxnode_wfile)
            # del(self.nxnode_commfd)
            nxlog.setup('nxserver-outer')
            nxlog.log(nxlog.LOG_INFO,
                      "Forked child to take care of nxsession stuff")
            return False

        # Dissociate from the nxserver terminal
        os.setsid()

        # If we need to change signal behavior, do it here.

        # Close the stdio fds.
        os.close(0)
        os.close(1)
        os.close(2)

        self.input = self.nxnode_rfile
        self.output = self.nxnode_wfile

        # I'm not sure what to do here with self.nxnode_rfile and self.nxnode_wfile
        # Closing the fd is enough, but the file objects would linger on.
        del (self.nxnode_rfile)
        del (self.nxnode_wfile)
        del (self.nxnode_commfd)

        nxlog.setup('nxserver-inner')
        nxlog.log(nxlog.LOG_INFO, "Successfully forked, "
                  "taking care of nxsession stuff\n")
        try:
            self._session_read_loop()
        except Exception:
            trace = traceback.format_exc()
            nxlog.log(
                nxlog.LOG_ERR, 'Going down because exception caught '
                'at the top level.')
            for line in trace.split('\n'):
                nxlog.log(nxlog.LOG_ERR, '%s' % line)
        return True
Example #26
0
    def write(self,
              output,
              newline=True,
              flush=True,
              log=True,
              log_level=nxlog.LOG_DEBUG,
              fd=None):
        """Write given string to output, and optionally:
          - append a newline
          - flush output afterwards
          - log the output, with a specified log level."""

        if newline:
            output += '\n'
        use_fd = self.output
        if fd:
            use_fd = fd
        use_fd.write(output)
        if flush:
            use_fd.flush()
        if log:
            nxlog.log(log_level, 'Sent: %r\n' % output)
Example #27
0
  def daemonize(self):
    """Drop into the background."""

    # I am assumuing this throws if fork fails.
    pid = os.fork()
    # In the parent, return.
    if pid != 0:
      # self.nxnode_rfile.close()
      # self.nxnode_wfile.close()
      os.close(self.nxnode_commfd)
      # del(self.nxnode_rfile)
      # del(self.nxnode_wfile)
      # del(self.nxnode_commfd)
      nxlog.setup('nxserver-outer')
      nxlog.log(nxlog.LOG_INFO, "Forked child to take care of nxsession stuff")
      return False

    # Dissociate from the nxserver terminal
    os.setsid()

    # If we need to change signal behavior, do it here.

    # Close the stdio fds.
    os.close(0)
    os.close(1)
    os.close(2)

    self.input = self.nxnode_rfile
    self.output = self.nxnode_wfile

    # I'm not sure what to do here with self.nxnode_rfile and self.nxnode_wfile
    # Closing the fd is enough, but the file objects would linger on.
    del(self.nxnode_rfile)
    del(self.nxnode_wfile)
    del(self.nxnode_commfd)

    nxlog.setup('nxserver-inner')
    nxlog.log(nxlog.LOG_INFO, "Successfully forked, "
        "taking care of nxsession stuff\n")
    try:
      self._session_read_loop()
    except Exception:
      trace = traceback.format_exc()
      nxlog.log(nxlog.LOG_ERR, 'Going down because exception caught '
                               'at the top level.')
      for line in trace.split('\n'):
        nxlog.log(nxlog.LOG_ERR, '%s' % line)
    return True
def check_dir_var(varname, defval):
  def is_valid(path):
    return path is not None and os.path.isdir(path)

  global __conf_errors
  varval = conf.get(varname)

  if varval is not None: # Is there a value set already?
    if is_valid(varval):
      return True # Everything checks out.
    else:
      nxlog.log(nxlog.LOG_WARNING, "Invalid directory variable %s: \"%s\"\n" %
          (varname, varval))

  if is_valid(defval):
    # Everything ok now
    conf[varname] = defval
    return True
  else:
    nxlog.log(nxlog.LOG_ERR, "Invalid default directory variable %s: \"%s\"\n" %
        (varname, defval))
    __conf_errors = True
    return False
Example #29
0
    def _nx_startsession_handler(self, command):
        # Remove 'startsession' from the front of the list of args
        command.pop(0)

        id = command.pop(0)
        req = {}
        for param in command:
            key, val = self._parse_param(param)
            if key:
                req[key] = val
        sess = self.node_session(id, req)

        # FIXME(diamond): change number to something sensible
        self.write("NX> 8888 sessioncreate %s" % sess.info())
        # Let stdout go directly to our stdout, i.e. to nxserver
        # Check stderr for error messages if things go badly
        p = subprocess.Popen('/usr/freenx/bin/nxagent-helper',
                             stdin=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             shell=True)
        p.stdin.write('start %s\n' % sess.full_id)
        p.stdin.flush()
        nxlog.log(nxlog.LOG_DEBUG, 'Starting session')
        child_status = p.wait()
        if child_status != 0:
            lines = p.stderr.readlines()
            if not lines:
                out_msg = ", no output printed"
            else:
                out_msg = ", with %d lines of output (shown below):" % len(
                    lines)
            nxlog.log(nxlog.LOG_ERR,
                      'Start session failed %d%s' % (child_status, out_msg))
            for line in lines:
                nxlog.log(nxlog.LOG_ERR, 'from nxagent-helper: %s' % line)
            self.prompt(500, 'Error: Startsession failed')
            self.running = False
            return
        nxlog.log(nxlog.LOG_ERR, 'Session completed %d' % child_status)
        self.running = False
Example #30
0
  def _nx_startsession_handler(self, command):
    # Remove 'startsession' from the front of the list of args
    command.pop(0)

    id = command.pop(0)
    req = {}
    for param in command:
      key,val = self._parse_param(param)
      if key: req[key] = val
    sess = self.node_session(id, req)

    # FIXME(diamond): change number to something sensible
    self.write("NX> 8888 sessioncreate %s" % sess.info())
    # Let stdout go directly to our stdout, i.e. to nxserver
    # Check stderr for error messages if things go badly
    p = subprocess.Popen('/usr/freenx/bin/nxagent-helper',
                         stdin=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         shell=True)
    p.stdin.write('start %s\n' % sess.full_id)
    p.stdin.flush()
    nxlog.log(nxlog.LOG_DEBUG, 'Starting session')
    child_status = p.wait()
    if child_status != 0:
      lines = p.stderr.readlines()
      if not lines:
        out_msg = ", no output printed"
      else:
        out_msg = ", with %d lines of output (shown below):" % len(lines)
      nxlog.log(nxlog.LOG_ERR, 'Start session failed %d%s' %
          (child_status, out_msg))
      for line in lines:
        nxlog.log(nxlog.LOG_ERR, 'from nxagent-helper: %s' % line)
      self.prompt(500, 'Error: Startsession failed')
      self.running = False
      return
    nxlog.log(nxlog.LOG_ERR, 'Session completed %d' % child_status)
    self.running = False
Example #31
0
    def loop(self):
        """Write the protocol prompt to the output, and accept commands."""

        try:
            while self.running:
                self.prompt(self.state)
                line = self.input.readline()
                if not line:
                    nxlog.log(nxlog.LOG_DEBUG, "Exiting due to EOF")
                    return
                line = line.rstrip()
                nxlog.log(nxlog.LOG_DEBUG, 'Got %r' % line)
                command = line.split()
                if not command:
                    # If the line was all whitespace this could happen.
                    continue
                cmd = command[0].lower()
                if cmd == 'set':
                    self.write("%s %s: %s" %
                               (cmd.capitalize(), command[1].lower(),
                                command[2].lower()))
                elif cmd == 'startsession':
                    self.write("Start session with: %s" %
                               " ".join(command[1:]))
                else:
                    self.write(line.capitalize())
                if cmd not in self.NX_COMMANDS:
                    self.prompt(503, 'Error: undefined command: \'%s\'' % cmd)
                    continue
                handler_name = '_nx_%s_handler' % cmd
                try:
                    handler_method = getattr(self, handler_name)
                except AttributeError:
                    nxlog.log(nxlog.LOG_DEBUG, 'Unhandled nx command %r' % cmd)
                    continue
                handler_method(command)
        except IOError, e:
            nxlog.log(nxlog.LOG_ERR, 'IOError. Connection lost: %s' % e)
Example #32
0
  def loop(self):
    """Write the protocol prompt to the output, and accept commands."""

    try:
      while self.running:
        self.prompt(self.state)
        line = self.input.readline()
        if not line:
          nxlog.log(nxlog.LOG_DEBUG, "Exiting due to EOF")
          return
        line = line.rstrip()
        nxlog.log(nxlog.LOG_DEBUG, 'Got %r' % line)
        command = line.split()
        if not command:
          # If the line was all whitespace this could happen.
          continue
        cmd = command[0].lower()
        if cmd == 'set':
          self.write("%s %s: %s" % (cmd.capitalize(), command[1].lower(),
            command[2].lower()))
        elif cmd == 'startsession':
          self.write("Start session with: %s" % " ".join(command[1:]))
        else:
          self.write(line.capitalize())
        if cmd not in self.NX_COMMANDS:
          self.prompt(503, 'Error: undefined command: \'%s\'' % cmd)
          continue
        handler_name = '_nx_%s_handler' % cmd
        try:
          handler_method = getattr(self, handler_name)
        except AttributeError:
          nxlog.log(nxlog.LOG_DEBUG, 'Unhandled nx command %r' % cmd)
          continue
        handler_method(command)
    except IOError, e:
      nxlog.log(nxlog.LOG_ERR, 'IOError. Connection lost: %s' % e)
Example #33
0
            'cache=8M', 'images=32M', 'link=%(link)s' % self,
            'type=%(shorttype)s' % self, 'clipboard=both', 'composite=1',
            'cleanup=0', 'accept=127.0.0.1', 'product=Freenx-gpl', 'shmem=1',
            'backingstore=1', 'shpix=1', 'cookie=%s' % self.cookie,
            'id=%s' % self.full_id, 'strict=0']
        if self.type == 'unix-application':
          opts.append('application=%(application)s' % self)
        if self.fullscreen == '1':
          opts.append('fullscreen=%(fullscreen)s' % self)
        opts_file.write("%s:%d\n" % (",".join(opts), self.display))
        opts_file.close()
      except IOError, e:
        nxlog.log(nxlog.LOG_ERR, 'IOError when writing '
            'session options file: %s' % e)
      except OSError, e:
        nxlog.log(nxlog.LOG_ERR, 'OSError when writing '
            'session options file: %s' % e)

    def info(self): #This is for reporting back to nxserver
      """Return a string with all parameter values encoded into it"""
      # Needed for session list:
      #   Display number
      #   type
      #   id
      #   options(?) FRD--PSA (F=fullscreen, R=render,
      #              D=non-rootless(Desktop?), PSA?)
      #   depth
      #   resolution
      #   status
      #   name
      # Needed for session start:
      #   hostname
Example #34
0
    def testLog(self):
        """Test calling log function"""

        nxlog.log(0, "test log message")
Example #35
0
        sess.params['full_id'])

    # Needed to get nxagent to open it's port again.
    try:
      os.kill(int(sess.params['agent_pid']), signal.SIGHUP)
    except OSError, e:
      nxlog.log(nxlog.LOG_WARNING, "Attempted to send SIGHUP to nxagent, "
          "got error from kill[%d]: %s\n" % e.args)
      self.prompt(500, 'Error: Fatal error in module %s, '
          'check log file for more details.' % self.program.lower())
      self.prompt(999, 'Bye.')
      self.running = False
      return
    except (TypeError, ValueError), e:
      nxlog.log(nxlog.LOG_WARNING, "Session does not have a valid nxagent pid "
          "stored (instead has %r), got error: %s" %
          (sess.params['agent_pid'], e))
      self.prompt(500, 'Error: Fatal error in module %s, '
          'check log file for more details.' % self.program.lower())
      self.prompt(999, 'Bye.')
      self.running = False
      return
    else:
      nxlog.log(nxlog.LOG_NOTICE, "Sent SIGHUP to nxagent\n")

    self.__print_sess_info(sess)
    self.prompt(710, 'Session status: %s' % sess.params['state'])
    #FIXME(diamond): use configurable offset
    self.port = int(sess.params['display']) + 4000

  def daemonize(self):
Example #36
0
  def _nx_login_handler(self, unused_command):
    """Handle the login NX command.

    'login' is used to start the process of authenticating to NX. The username
    and password is send in response to requests from the server. If no
    options have been set, nxserver will ask for the password, and will then
    ask for an 'MD5 Password' if no password is given. If
    'SET AUTH_MODE PASSWORD' has been sent by the client, it does not do this
     however. This code currently never requests the MD5 Password. It is
    possible that making use of this feature requires storing the users
    password and verifying it with the hash.

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

    # Basic checking of the right status
    if self.status >= self.STATUS_LOGGEDIN:
      self.prompt(554, 'Error: the command \'login\' cannot be '
          'called after login')
      return
    self.prompt(101, 'User: '******'Error: Username is not in expected format')
      return
    self.write('') # Print newline after username
    self.username = split_line[0]
    nxlog.log(nxlog.LOG_DEBUG, 'Got user %r' % self.username)
    self.prompt(102, 'Password: '******'Got fd %r' % fd)
    # Save the terminal settings
    try:
      old = termios.tcgetattr(fd)
      new = old[:]

      # Disable the echo flag
      new[3] = new[3] & ~termios.ECHO # 3 == 'lflags'
      try:
        termios.tcsetattr(fd, termios.TCSADRAIN, new)
        passwd = self.input.readline()
      finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)
    except termios.error:
      passwd = self.input.readline()

    nxlog.log(nxlog.LOG_DEBUG, 'Got a passwd')

    self.write('\n')
    # FIXME(diamond): ssh to localhost to verify the username and password are
    # correct. Also store the authentication information we need in a secure
    # way.
    del passwd
    self.status = self.STATUS_LOGGEDIN
    self.banner()
Example #37
0
    def _nx_restoresession_handler(self, command):
        """Handle the restoresession NX command.

    'restoresession' requests an existing session be resume.
    It requires parameters be specified. The following parameters have
    been seen, at a minimum the session id must be specified:
    '--link="lan"'
    '--backingstore="1"'
    '--encryption="1"'
    '--cache="16M"'
    '--images="64M"'
    '--shmem="1"'
    '--shpix="1"'
    '--strict="0"'
    '--composite="1"'
    '--media="0"'
    '--session="localtest"'
    '--type="unix-gnome"'
    '--geometry="3840x1150"'
    '--client="linux"'
    '--keyboard="pc102/gb"'
    '--screeninfo="3840x1150x24+render"'
    --id="A28EBF5AAC354E9EEAFEEB867980C543"

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

        # Basic checking of the right status
        if self.status < self.STATUS_LOGGEDIN:
            self.prompt(
                554, 'Error: the command \'%s\' cannot '
                'be called before login' % command[0])
            return
        # Make sure the state is consistent
        assert (hasattr(self, 'username'))
        # Ask for parameters if none have been given
        if len(command) > 1:
            parameters = command[1:]
        else:
            self.prompt(106, 'Parameters: ', override_newline=False)
            response = self.input.readline()
            self.write('')  # Do newline after parameters.
            parameters = response.split()
        req = {}
        # Check the parameters fit with the expected syntax
        for param in parameters:
            key, val = self._parse_param(param)
            if key: req[key] = val
            # FIXME(diamond): DO something with the params.
        if not req.has_key('id'):
            msg = "Restore session requested, but no session specified"
            nxlog.log(nxlog.LOG_ERR, "%s (args: %r)\n" % (msg, req))
            self.prompt(500,
                        'Error: %s. check log file for more details.' % msg)
            self.running = False
            return
        nxlog.log(nxlog.LOG_DEBUG, "Got id param: %s" % req['id'])
        sessions = nxsession.db_find_sessions(id=req['id'],
                                              users=[self.username],
                                              states=['suspended', 'running'])
        if len(sessions) != 1:
            nxlog.log(
                nxlog.LOG_ERR, "%d sessions found matching %s in "
                "session db %s\n" % (len(sessions), req['id'], sessions))
            self.prompt(
                500, 'Error: Fatal error in module %s, '
                'check log file for more details.' % self.program.lower())
            self.running = False
            return

        sess = sessions[0]
        nxlog.log(nxlog.LOG_DEBUG,
                  "Session %s found in session db\n" % sess.params['full_id'])

        # Needed to get nxagent to open it's port again.
        try:
            os.kill(int(sess.params['agent_pid']), signal.SIGHUP)
        except OSError, e:
            nxlog.log(
                nxlog.LOG_WARNING, "Attempted to send SIGHUP to nxagent, "
                "got error from kill[%d]: %s\n" % e.args)
            self.prompt(
                500, 'Error: Fatal error in module %s, '
                'check log file for more details.' % self.program.lower())
            self.prompt(999, 'Bye.')
            self.running = False
            return
Example #38
0
 def _nx_resumesession_handler(self, unused_command):
   nxlog.log(nxlog.LOG_DEBUG, 'Resuming session')
Example #39
0
  def _nx_restoresession_handler(self, command):
    """Handle the restoresession NX command.

    'restoresession' requests an existing session be resume.
    It requires parameters be specified. The following parameters have
    been seen, at a minimum the session id must be specified:
    '--link="lan"'
    '--backingstore="1"'
    '--encryption="1"'
    '--cache="16M"'
    '--images="64M"'
    '--shmem="1"'
    '--shpix="1"'
    '--strict="0"'
    '--composite="1"'
    '--media="0"'
    '--session="localtest"'
    '--type="unix-gnome"'
    '--geometry="3840x1150"'
    '--client="linux"'
    '--keyboard="pc102/gb"'
    '--screeninfo="3840x1150x24+render"'
    --id="A28EBF5AAC354E9EEAFEEB867980C543"

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

    # Basic checking of the right status
    if self.status < self.STATUS_LOGGEDIN:
      self.prompt(554, 'Error: the command \'%s\' cannot '
          'be called before login' % command[0])
      return
    # Make sure the state is consistent
    assert(hasattr(self, 'username'))
    # Ask for parameters if none have been given
    if len(command) > 1:
      parameters = command[1:]
    else:
      self.prompt(106, 'Parameters: ', override_newline=False)
      response = self.input.readline()
      self.write('') # Do newline after parameters.
      parameters = response.split()
    req = {}
    # Check the parameters fit with the expected syntax
    for param in parameters:
      key,val = self._parse_param(param)
      if key: req[key] = val
      # FIXME(diamond): DO something with the params.
    if not req.has_key('id'):
      msg = "Restore session requested, but no session specified"
      nxlog.log(nxlog.LOG_ERR, "%s (args: %r)\n" % (msg, req))
      self.prompt(500, 'Error: %s. check log file for more details.' % msg)
      self.running = False
      return
    nxlog.log(nxlog.LOG_DEBUG, "Got id param: %s" % req['id'])
    sessions = nxsession.db_find_sessions(id=req['id'], users=[self.username],
        states=['suspended', 'running'])
    if len(sessions) != 1:
      nxlog.log(nxlog.LOG_ERR, "%d sessions found matching %s in "
          "session db %s\n" % (len(sessions), req['id'], sessions))
      self.prompt(500, 'Error: Fatal error in module %s, '
          'check log file for more details.' % self.program.lower())
      self.running = False
      return

    sess = sessions[0]
    nxlog.log(nxlog.LOG_DEBUG, "Session %s found in session db\n" %
        sess.params['full_id'])

    # Needed to get nxagent to open it's port again.
    try:
      os.kill(int(sess.params['agent_pid']), signal.SIGHUP)
    except OSError, e:
      nxlog.log(nxlog.LOG_WARNING, "Attempted to send SIGHUP to nxagent, "
          "got error from kill[%d]: %s\n" % e.args)
      self.prompt(500, 'Error: Fatal error in module %s, '
          'check log file for more details.' % self.program.lower())
      self.prompt(999, 'Bye.')
      self.running = False
      return
Example #40
0
 def _session_read_loop(self):
   sess = None
   while True:
     line = self.input.readline()
     if not line:
       return
     line = line.rstrip()
     nxlog.log(nxlog.LOG_DEBUG, 'Got from nxnode %r\n' % line)
     # FIXME(diamond): change number to something sensible
     if line.startswith('NX> 8888 sessioncreate'):
       if sess:
         nxlog.log(nxlog.LOG_ERR, 'Nxnode tried to create a session when one '
             'already exists: %s\n' % line)
       else:
         args = line.split(' ', 3)[-1].replace(' ', '\n')
         sess = nxsession.nxsession(args)
     elif line.startswith('NX> 8888 agentpid:'):
       if not sess:
         nxlog.log(nxlog.LOG_ERR, 'Nxagent-helper tried to change session '
             'when none exists: %s\n' % line)
       else:
         agent_pid = line.rstrip().split(' ')[3]
         sess.params['agent_pid'] = agent_pid
         sess.save()
         nxlog.log(nxlog.LOG_DEBUG, "Agent pid set to '%s'\n" %
             sess.params['agent_pid'])
     elif line.startswith('NX> 1009 Session status:'):
       if not sess:
         nxlog.log(nxlog.LOG_ERR, 'Nxagent-helper tried to change session '
             'when none exists: %s\n' % line)
       else:
         state_name = line.rstrip().split(' ')[4]
         sess.set_state(state_name)
         sess.save()
         nxlog.log(nxlog.LOG_DEBUG, "Session state updated to '%s'\n" %
             sess.params['state'])
     elif line.startswith('NX> 500 Error:'):
       if sess:
         sess.set_state('terminated')
         sess.save()
         nxlog.log(nxlog.LOG_DEBUG, "Session state updated to '%s', exiting\n"
             % sess.params['state'])
         break
Example #41
0
        # Needed to get nxagent to open it's port again.
        try:
            os.kill(int(sess.params['agent_pid']), signal.SIGHUP)
        except OSError, e:
            nxlog.log(
                nxlog.LOG_WARNING, "Attempted to send SIGHUP to nxagent, "
                "got error from kill[%d]: %s\n" % e.args)
            self.prompt(
                500, 'Error: Fatal error in module %s, '
                'check log file for more details.' % self.program.lower())
            self.prompt(999, 'Bye.')
            self.running = False
            return
        except (TypeError, ValueError), e:
            nxlog.log(
                nxlog.LOG_WARNING, "Session does not have a valid nxagent pid "
                "stored (instead has %r), got error: %s" %
                (sess.params['agent_pid'], e))
            self.prompt(
                500, 'Error: Fatal error in module %s, '
                'check log file for more details.' % self.program.lower())
            self.prompt(999, 'Bye.')
            self.running = False
            return
        else:
            nxlog.log(nxlog.LOG_NOTICE, "Sent SIGHUP to nxagent\n")

        self.__print_sess_info(sess)
        self.prompt(710, 'Session status: %s' % sess.params['state'])
        #FIXME(diamond): use configurable offset
        self.port = int(sess.params['display']) + 4000
Example #42
0
    def _nx_login_handler(self, unused_command):
        """Handle the login NX command.

    'login' is used to start the process of authenticating to NX. The username
    and password is send in response to requests from the server. If no
    options have been set, nxserver will ask for the password, and will then
    ask for an 'MD5 Password' if no password is given. If
    'SET AUTH_MODE PASSWORD' has been sent by the client, it does not do this
     however. This code currently never requests the MD5 Password. It is
    possible that making use of this feature requires storing the users
    password and verifying it with the hash.

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

        # Basic checking of the right status
        if self.status >= self.STATUS_LOGGEDIN:
            self.prompt(
                554, 'Error: the command \'login\' cannot be '
                'called after login')
            return
        self.prompt(101, 'User: '******'Error: Username is not in expected format')
            return
        self.write('')  # Print newline after username
        self.username = split_line[0]
        nxlog.log(nxlog.LOG_DEBUG, 'Got user %r' % self.username)
        self.prompt(102, 'Password: '******'Got fd %r' % fd)
        # Save the terminal settings
        try:
            old = termios.tcgetattr(fd)
            new = old[:]

            # Disable the echo flag
            new[3] = new[3] & ~termios.ECHO  # 3 == 'lflags'
            try:
                termios.tcsetattr(fd, termios.TCSADRAIN, new)
                passwd = self.input.readline()
            finally:
                termios.tcsetattr(fd, termios.TCSADRAIN, old)
        except termios.error:
            passwd = self.input.readline()

        nxlog.log(nxlog.LOG_DEBUG, 'Got a passwd')

        self.write('\n')
        # FIXME(diamond): ssh to localhost to verify the username and password are
        # correct. Also store the authentication information we need in a secure
        # way.
        del passwd
        self.status = self.STATUS_LOGGEDIN
        self.banner()
Example #43
0
    def _nx_startsession_handler(self, command):
        """Handle the startsession NX command.

    'startsession' seems to request a new session be started.
    It requires parameters be specified. The following parameters have
    been seen.
    '--link="lan"'
    '--backingstore="1"'
    '--encryption="1"'
    '--cache="16M"'
    '--images="64M"'
    '--shmem="1"'
    '--shpix="1"'
    '--strict="0"'
    '--composite="1"'
    '--media="0"'
    '--session="localtest"'
    '--type="unix-gnome"'
    '--geometry="3840x1150"'
    '--client="linux"'
    '--keyboard="pc102/gb"'
    '--screeninfo="3840x1150x24+render"'
    Experiments with this command by directly invoked nxserver have not
    worked, as it refuses to create a session saying the unencrypted sessions
    are not supported. This is independent of whether the --encryption option
    has been set, so probably is related to the fact the nxserver has not
    been launched by sshd.

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

        # Basic checking of the right status
        if self.status < self.STATUS_LOGGEDIN:
            self.prompt(
                554, 'Error: the command \'%s\' cannot '
                'be called before login' % command[0])
            return
        # Make sure the state is consistent
        assert (hasattr(self, 'username'))
        # Ask for parameters if none have been given
        if len(command) > 1:
            parameters = command[1:]
        else:
            self.prompt(106, 'Parameters: ', override_newline=False)
            response = self.input.readline()
            self.write('')  # Do newline after parameters.
            parameters = response.split()
        # Check the parameters fit with the expected syntax
        for param in parameters:
            key, val = self._parse_param(param)
            # FIXME(diamond): DO something with the params.
        # FIXME(diamond): Start the session.
        if not hasattr(self, 'nxnode_commfd'):
            nxlog.log(nxlog.LOG_ERR, 'Nxserver does not have an nxnode yet.')
            return
        # Send the command to the connected nxnode running
        # FIXME(diamond): Convert the arguments to the form expected by nxnode.
        sess_id = nxsession.gen_uniq_id()
        self.write('startsession %s %s' % (sess_id, " ".join(parameters)),
                   fd=self.nxnode_wfile)

        if self.daemonize():
            # Two threads return here, one connected to the client, one connected to
            # nxnode.
            self.running = False
            return

        start_waiting = time.time()
        wait_time = 30  #FIXME(diamond): make configurable
        while True:
            if time.time() - start_waiting > wait_time:
                nxlog.log(
                    nxlog.LOG_ERR, "Session %s has not appeared in session db "
                    "within %d seconds\n" % (sess_id, wait_time))
                sys.exit(1)
                #FIXME(diamond): raise proper error
            sessions = nxsession.db_find_sessions(id=sess_id)
            if len(sessions) == 1:
                sess = sessions[0]
                nxlog.log(
                    nxlog.LOG_DEBUG,
                    "Session %s has appeared in session db\n" %
                    sess.params['full_id'])
                break
            elif len(sessions) > 1:
                nxlog.log(
                    nxlog.LOG_DEBUG, "Multiple sessions matching %d have been "
                    "found in the session db: %r\n" % sess_id)
                #FIXME(diamond): raise proper error
                break
            else:
                time.sleep(1)

        self.__print_sess_info(sess)

        start_waiting = time.time()
        wait_time = 30  #FIXME(diamond): make configurable
        while True:
            if time.time() - start_waiting > wait_time:
                nxlog.log(
                    nxlog.LOG_ERR,
                    "Session %s has not achieved running status "
                    "within %d seconds\n" % (sess_id, wait_time))
                sys.exit(1)
                #FIXME(diamond): raise proper error
            sess.reload()
            if sess.params['state'] == 'starting':
                break
            elif sess.params['state'] in ['terminating', 'terminated']:
                nxlog.log(
                    nxlog.LOG_ERR, "Session %(full_id)s has status "
                    "'%(state)s', exiting." % sess.params)
                self.prompt(
                    500, "Error: Session %(full_id)s has status '%(state)s'." %
                    sess.params)
                self.prompt(999, "Bye.")
                self.running = False
                return
                #FIXME(diamond): raise proper error
            else:
                time.sleep(1)
        self.prompt(710, 'Session status: %s' % sess.params['state'])
        #FIXME(diamond): use configurable offset
        self.port = int(sess.params['display']) + 4000
Example #44
0
class parser:
    """Base parser for NX protocol parsers.

    This class handles breaking up the messages into components,
    and dispatching them.
    """

    DEFAULT_VERSION = '3.0.0'
    DEFAULT_PROGRAM = 'NXBASE'

    NX_PROMPT = 'NX>'
    NX_COMMANDS = [
        'hello', 'login', 'bye', 'set', 'listsession', 'restoresession',
        'startsession', 'terminate'
    ]
    NX_PARAM_RX = re.compile(r'^--(?P<key>[a-z]+)="(?P<value>.+)"')

    def __init__(self,
                 input,
                 output,
                 version=DEFAULT_VERSION,
                 program=DEFAULT_PROGRAM):
        """base_parser constructor

        Args:
          input: The file object to read parser input from.
          output: The file object to write the results to.
          version: The version string used to negotiate the protocol.
          program: The program name used in the protocol banner.
        """

        self.input = input
        self.output = output
        self.state = 105
        self.running = True
        self.parse_args(version=version, program=program)
        nxlog.log(nxlog.LOG_DEBUG,
                  "Version: %s Program: %s" % (self.version, self.program))

    def banner(self):
        """Write the protocol banner to the output."""

        self.write('HELLO %s - Version %s - GPL' %
                   (self.program, self.version))

    def prompt(self, state, message='', override_newline=None):
        """Write the protocol prompt to the output.

        If no message is given, just print the prompt & state, no newline.
        If a message is provided, by default append a newline.

        Args:
          state: The state number to put after the NX> prompt
          message: Optional message to print after the state
          override_newline: Optional param to force a trailing newline on/off"""

        newline = False
        if override_newline is not None:
            newline = override_newline
        elif message:
            newline = True
        self.write('%s %d %s' % (self.NX_PROMPT, state, message),
                   newline=newline)

    def loop(self):
        """Write the protocol prompt to the output, and accept commands."""

        try:
            while self.running:
                self.prompt(self.state)
                line = self.input.readline()
                if not line:
                    nxlog.log(nxlog.LOG_DEBUG, "Exiting due to EOF")
                    return
                line = line.rstrip()
                nxlog.log(nxlog.LOG_DEBUG, 'Got %r' % line)
                command = line.split()
                if not command:
                    # If the line was all whitespace this could happen.
                    continue
                cmd = command[0].lower()
                if cmd == 'set':
                    self.write("%s %s: %s" %
                               (cmd.capitalize(), command[1].lower(),
                                command[2].lower()))
                elif cmd == 'startsession':
                    self.write("Start session with: %s" %
                               " ".join(command[1:]))
                else:
                    self.write(line.capitalize())
                if cmd not in self.NX_COMMANDS:
                    self.prompt(503, 'Error: undefined command: \'%s\'' % cmd)
                    continue
                handler_name = '_nx_%s_handler' % cmd
                try:
                    handler_method = getattr(self, handler_name)
                except AttributeError:
                    nxlog.log(nxlog.LOG_DEBUG, 'Unhandled nx command %r' % cmd)
                    continue
                handler_method(command)
        except IOError, e:
            nxlog.log(nxlog.LOG_ERR, 'IOError. Connection lost: %s' % e)
        except Exception, e:
            trace = traceback.format_exc()
            nxlog.log(
                nxlog.LOG_ERR, 'Going down because exception caught '
                'at the top level.')
            for line in trace.split('\n'):
                nxlog.log(nxlog.LOG_ERR, '%s' % line)
            self.prompt(
                500, 'Error: Fatal error in module %s, '
                'check log file for more details.' % self.program.lower())
            self.prompt(999, 'Bye.')
Example #45
0
  def _nx_startsession_handler(self, command):
    """Handle the startsession NX command.

    'startsession' seems to request a new session be started.
    It requires parameters be specified. The following parameters have
    been seen.
    '--link="lan"'
    '--backingstore="1"'
    '--encryption="1"'
    '--cache="16M"'
    '--images="64M"'
    '--shmem="1"'
    '--shpix="1"'
    '--strict="0"'
    '--composite="1"'
    '--media="0"'
    '--session="localtest"'
    '--type="unix-gnome"'
    '--geometry="3840x1150"'
    '--client="linux"'
    '--keyboard="pc102/gb"'
    '--screeninfo="3840x1150x24+render"'
    Experiments with this command by directly invoked nxserver have not
    worked, as it refuses to create a session saying the unencrypted sessions
    are not supported. This is independent of whether the --encryption option
    has been set, so probably is related to the fact the nxserver has not
    been launched by sshd.

    Args:
      command: The NX command and arguments invoked

    Returns:
      None
    """

    # Basic checking of the right status
    if self.status < self.STATUS_LOGGEDIN:
      self.prompt(554, 'Error: the command \'%s\' cannot '
          'be called before login' % command[0])
      return
    # Make sure the state is consistent
    assert(hasattr(self, 'username'))
    # Ask for parameters if none have been given
    if len(command) > 1:
      parameters = command[1:]
    else:
      self.prompt(106, 'Parameters: ', override_newline=False)
      response = self.input.readline()
      self.write('') # Do newline after parameters.
      parameters = response.split()
    # Check the parameters fit with the expected syntax
    for param in parameters:
      key,val = self._parse_param(param)
      # FIXME(diamond): DO something with the params.
    # FIXME(diamond): Start the session.
    if not hasattr(self, 'nxnode_commfd'):
      nxlog.log(nxlog.LOG_ERR, 'Nxserver does not have an nxnode yet.')
      return
    # Send the command to the connected nxnode running
    # FIXME(diamond): Convert the arguments to the form expected by nxnode.
    sess_id = nxsession.gen_uniq_id()
    self.write('startsession %s %s' %
        (sess_id, " ".join(parameters)), fd=self.nxnode_wfile)

    if self.daemonize():
    # Two threads return here, one connected to the client, one connected to
    # nxnode.
      self.running = False
      return

    start_waiting = time.time()
    wait_time = 30 #FIXME(diamond): make configurable
    while True:
      if time.time() - start_waiting > wait_time:
        nxlog.log(nxlog.LOG_ERR, "Session %s has not appeared in session db "
            "within %d seconds\n" % (sess_id, wait_time))
        sys.exit(1)
        #FIXME(diamond): raise proper error
      sessions = nxsession.db_find_sessions(id=sess_id)
      if len(sessions) == 1:
        sess = sessions[0]
        nxlog.log(nxlog.LOG_DEBUG, "Session %s has appeared in session db\n" %
            sess.params['full_id'])
        break
      elif len(sessions) > 1:
        nxlog.log(nxlog.LOG_DEBUG, "Multiple sessions matching %d have been "
            "found in the session db: %r\n" % sess_id)
        #FIXME(diamond): raise proper error
        break
      else:
        time.sleep(1)

    self.__print_sess_info(sess)

    start_waiting = time.time()
    wait_time = 30 #FIXME(diamond): make configurable
    while True:
      if time.time() - start_waiting > wait_time:
        nxlog.log(nxlog.LOG_ERR, "Session %s has not achieved running status "
            "within %d seconds\n" % (sess_id, wait_time))
        sys.exit(1)
        #FIXME(diamond): raise proper error
      sess.reload()
      if sess.params['state'] == 'starting':
        break
      elif sess.params['state'] in ['terminating', 'terminated']:
        nxlog.log(nxlog.LOG_ERR, "Session %(full_id)s has status "
            "'%(state)s', exiting." % sess.params)
        self.prompt(500, "Error: Session %(full_id)s has status '%(state)s'." %
            sess.params)
        self.prompt(999, "Bye.")
        self.running = False
        return
        #FIXME(diamond): raise proper error
      else:
        time.sleep(1)
    self.prompt(710, 'Session status: %s' % sess.params['state'])
    #FIXME(diamond): use configurable offset
    self.port = int(sess.params['display']) + 4000
Example #46
0
  def testLog(self):
    """Test calling log function"""

    nxlog.log(0, 'test log message')
Example #47
0
  class node_session:
    """Internal representation of a session

    This class is used by nxnode to store session parameters, to create the
    needed session args & options file, and to print out the parameters for
    transmission to nxserver-inner.
    """

    def __init__(self, id, args):
      """node_session constructor

      Args:
        args: The id of the session, followed by all the other
              parameters the client requested
      """

      self.id = id
      self.args = args
      self.display = self._gen_disp_num()
      self.hostname = socket.getfqdn()
      self.full_id = "%s-%s-%s" % (self.hostname, self.display, self.id)
      self.cookie = nxsession.gen_uniq_id()
      self.dir = os.path.join('/tmp/nx', 'S-%s' % self.full_id)
      #FIXME(diamond): needs error checking, maybe different mode
      os.makedirs(self.dir, 0755)
      self.opts_file_path = os.path.join(self.dir, 'options') 
      self.args_file_path = os.path.join(self.dir, 'args') 
      self.application = self.args.get('application')
      self.user = pwd.getpwuid(os.getuid())[0]
      self.name = self.args.get('session', "%s:%s" % (self.hostname, self.display))
      self.keyboard = self.args.get('keyboard', 'pc105/gb')
      self.geometry = self.args.get('geometry', '640x480')
      self.client = self.args.get('client', 'unknown')
      self.link = self.args.get('link', 'isdn')
      self.fullscreen = self.args.get('fullscreen', '0')
      #DEBUG, FIXME(diamond): all of these
      self.type = self.args.get('type', 'unix-default')
      self.options = '-----PSA' #FIXME(diamond): see note in self.info()
      self.depth = 24
      self.resolution = "640x480"
      #FIXME(diamond): Not ipv6 compatible
      self.proxyip = socket.gethostbyname(self.hostname)
      self.ssl = 1
      #End DEBUG/FIXME(diamond)

      if self.type == 'unix-application':
        assert(self.application)
        self.mode = '-R' # Run nxagent in rootless mode
      else:
        self.mode = '-D' # Run nxagent in desktop mode

      # We need to write the type without the 'unix-' prefix for nxagent.
      if self.type.startswith('unix-'):
        self.shorttype = self.type.split('-', 1)[1]
      else:
        self.shorttype = self.type

      self._write_args()
      self._write_opts()

    def __getitem__(self, item):
      """Allow node_session instances to be treated as dicts

      This is used in places like self.info(), to allow cleaner variable
      substitution of variables in strings.
      """

      return getattr(self, item)

    def _gen_disp_num(self):
      """Return an unused display number (corresponding to an unused port)"""
      return 20 #DEBUG, FIXME(diamond)

    def _write_args(self):
      """Create the session's 'args' file

      The args file is a newline-delimited list of arguments to be passed to
      nxagent
      """

      try:
        args_file = open(self.args_file_path, 'w')
        #DEBUG, FIXME(diamond):
        args_file.write("\n".join([self.mode, '-options', self.opts_file_path,
          '-name', 'FreeNX - %(user)s@%(hostname)s:%(display)s' % self,
          '-nolisten', 'tcp', ':%d' % self.display]))
        args_file.write("\n")
        args_file.close()
      except IOError, e:
        nxlog.log(nxlog.LOG_ERR, 'IOError when writing '
            'session args file: %s' % e)
      except OSError, e:
        nxlog.log(nxlog.LOG_ERR, 'OSError when writing '
            'session args file: %s' % e)
Example #48
0
 def _session_read_loop(self):
     sess = None
     while True:
         line = self.input.readline()
         if not line:
             return
         line = line.rstrip()
         nxlog.log(nxlog.LOG_DEBUG, 'Got from nxnode %r\n' % line)
         # FIXME(diamond): change number to something sensible
         if line.startswith('NX> 8888 sessioncreate'):
             if sess:
                 nxlog.log(
                     nxlog.LOG_ERR,
                     'Nxnode tried to create a session when one '
                     'already exists: %s\n' % line)
             else:
                 args = line.split(' ', 3)[-1].replace(' ', '\n')
                 sess = nxsession.nxsession(args)
         elif line.startswith('NX> 8888 agentpid:'):
             if not sess:
                 nxlog.log(
                     nxlog.LOG_ERR,
                     'Nxagent-helper tried to change session '
                     'when none exists: %s\n' % line)
             else:
                 agent_pid = line.rstrip().split(' ')[3]
                 sess.params['agent_pid'] = agent_pid
                 sess.save()
                 nxlog.log(
                     nxlog.LOG_DEBUG,
                     "Agent pid set to '%s'\n" % sess.params['agent_pid'])
         elif line.startswith('NX> 1009 Session status:'):
             if not sess:
                 nxlog.log(
                     nxlog.LOG_ERR,
                     'Nxagent-helper tried to change session '
                     'when none exists: %s\n' % line)
             else:
                 state_name = line.rstrip().split(' ')[4]
                 sess.set_state(state_name)
                 sess.save()
                 nxlog.log(
                     nxlog.LOG_DEBUG, "Session state updated to '%s'\n" %
                     sess.params['state'])
         elif line.startswith('NX> 500 Error:'):
             if sess:
                 sess.set_state('terminated')
                 sess.save()
                 nxlog.log(
                     nxlog.LOG_DEBUG,
                     "Session state updated to '%s', exiting\n" %
                     sess.params['state'])
                 break