Exemplo n.º 1
0
def scan( host=get_hostname(), db=None, pyro_timeout=None, verbose=False, silent=False ):
    #print 'SCANNING PORTS'
    # scan all cylc Pyro ports for cylc suites

    gcfg = get_global_cfg(verbose=verbose)
    pyro_base_port = gcfg.cfg['pyro']['base port']
    pyro_port_range = gcfg.cfg['pyro']['maximum number of ports']

    # In non-verbose mode print nothing (scan is used by cylc db viewer).

    # load my suite passphrases 
    reg = localdb(db)
    reg_suites = reg.get_list()
    my_passphrases = {}
    for item in reg_suites:
        rg = item[0]
        di = item[1]
        try:
            pp = passphrase( rg, user, host ).get( suitedir=di )
        except Exception, x:
            #print >> sys.stderr, x
            # no passphrase defined for this suite
            pass
        else:
            my_passphrases[ rg ] = pp
Exemplo n.º 2
0
 def __init__( self, suite, pphrase=None, owner=user, host=get_hostname(),
         pyro_timeout=None, port=None ):
     self.suite = suite
     self.owner = owner
     self.host = host
     self.port = port
     if pyro_timeout:
         self.pyro_timeout = float(pyro_timeout)
     else:
         self.pyro_timeout = None
     self.pphrase = pphrase
Exemplo n.º 3
0
def get_port(suite,
             owner=user,
             host=get_hostname(),
             pphrase=None,
             pyro_timeout=None):
    # Scan ports until a particular suite is found.

    pyro_base_port = GLOBAL_CFG.get(['pyro', 'base port'])
    pyro_port_range = GLOBAL_CFG.get(['pyro', 'maximum number of ports'])

    for port in range(pyro_base_port, pyro_base_port + pyro_port_range):
        uri = cylcid_uri(host, port)
        try:
            proxy = Pyro.core.getProxyForURI(uri)
        except Pyro.errors.URIError, x:
            # No such host?
            raise SuiteNotFoundError, x

        if pyro_timeout:  # convert from string
            pyro_timeout = float(pyro_timeout)

        proxy._setTimeout(pyro_timeout)
        proxy._setIdentification(pphrase)

        before = datetime.datetime.now()
        try:
            name, xowner = proxy.id()
        except Pyro.errors.TimeoutError:
            warn_timeout(host, port, pyro_timeout)
            pass
        except Pyro.errors.ConnectionDeniedError:
            #print >> sys.stderr, "Wrong suite or wrong passphrase at " + portid( host, port )
            pass
        except Pyro.errors.ProtocolError:
            #print >> sys.stderr, "No Suite Found at " + portid( host, port )
            pass
        except Pyro.errors.NamingError:
            #print >> sys.stderr, "Non-cylc pyro server found at " + portid( host, port )
            pass
        else:
            if flags.verbose:
                after = datetime.datetime.now()
                print "Pyro connection on port " + str(port) + " took: " + str(
                    after - before)
            if name == suite and xowner == owner:
                if flags.verbose:
                    print suite, owner, host, port
                # RESULT
                return port
            else:
                # ID'd some other suite.
                #print 'OTHER SUITE:', name, xowner, host, port
                pass
Exemplo n.º 4
0
def get_port( suite, owner=user, host=get_hostname(), pphrase=None, pyro_timeout=None, verbose=False ):
    # Scan ports until a particular suite is found.

    gcfg = get_global_cfg(verbose=verbose)
    pyro_base_port = gcfg.cfg['pyro']['base port']
    pyro_port_range = gcfg.cfg['pyro']['maximum number of ports']

    for port in range( pyro_base_port, pyro_base_port + pyro_port_range ):
        uri = cylcid_uri( host, port )
        try:
            proxy = Pyro.core.getProxyForURI(uri)
        except Pyro.errors.URIError, x:
            # No such host?
            raise SuiteNotFoundError, x

        if pyro_timeout: # convert from string
            pyro_timeout = float( pyro_timeout )

        proxy._setTimeout(pyro_timeout)
        proxy._setIdentification( pphrase )

        before = datetime.datetime.now()
        try:
            name, xowner = proxy.id()
        except Pyro.errors.TimeoutError:
            warn_timeout( host, port, pyro_timeout )
            pass
        except Pyro.errors.ConnectionDeniedError:
            #print >> sys.stderr, "Wrong suite or wrong passphrase at " + portid( host, port )
            pass
        except Pyro.errors.ProtocolError:
            #print >> sys.stderr, "No Suite Found at " + portid( host, port )
            pass
        except Pyro.errors.NamingError:
            #print >> sys.stderr, "Non-cylc pyro server found at " + portid( host, port )
            pass
        else:
            if verbose:
                after = datetime.datetime.now()
                print "Pyro connection on port " +str(port) + " took: " + str( after - before )
            if name == suite and xowner == owner:
                if verbose:
                    print suite, owner, host, port
                # RESULT
                return port
            else:
                # ID'd some other suite.
                #print 'OTHER SUITE:', name, xowner, host, port
                pass
Exemplo n.º 5
0
 def __init__(self,
              suite,
              pphrase=None,
              owner=user,
              host=get_hostname(),
              pyro_timeout=None,
              port=None):
     self.suite = suite
     self.owner = owner
     self.host = host
     self.port = port
     if pyro_timeout:
         self.pyro_timeout = float(pyro_timeout)
     else:
         self.pyro_timeout = None
     self.pphrase = pphrase
Exemplo n.º 6
0
def check_port(suite,
               pphrase,
               port,
               owner=user,
               host=get_hostname(),
               pyro_timeout=None):
    # is a particular suite running at host:port?

    uri = cylcid_uri(host, port)
    proxy = Pyro.core.getProxyForURI(uri)
    if pyro_timeout:  # convert from string
        pyro_timeout = float(pyro_timeout)
    proxy._setTimeout(pyro_timeout)

    proxy._setIdentification(pphrase)

    before = datetime.datetime.now()
    try:
        name, xowner = proxy.id()
    except Pyro.errors.TimeoutError:
        warn_timeout(host, port, pyro_timeout)
        raise ConnectionTimedOutError, "ERROR, Connection Timed Out " + portid(
            host, port)
    except Pyro.errors.ConnectionDeniedError:
        raise ConnectionDeniedError, "ERROR: Connection Denied  at " + portid(
            host, port)
    except Pyro.errors.ProtocolError:
        raise NoSuiteFoundError, "ERROR: " + suite + " not found at " + portid(
            host, port)
    except Pyro.errors.NamingError:
        raise OtherServerFoundError, "ERROR: non-cylc pyro server found at " + portid(
            host, port)
    else:
        if flags.verbose:
            after = datetime.datetime.now()
            print "Pyro connection on port " + str(port) + " took: " + str(
                after - before)
        if name == suite and xowner == owner:
            # RESULT
            if flags.verbose:
                print suite, owner, host, port
            return True
        else:
            # ID'd some other suite.
            print >> sys.stderr, 'Found ' + name + ' ' + xowner + ' ' + host + ' ' + port
            print >> sys.stderr, ' NOT ' + suite + ' ' + owner + ' ' + host + ' ' + port
            raise OtherSuiteFoundError, "ERROR: Found another suite"
Exemplo n.º 7
0
    def __init__( self, suite, suitedir, base_port, max_n_ports, user=user ):

        self.suite = suite
        self.owner = user

        # SINGLE THREADED PYRO
        Pyro.config.PYRO_MULTITHREADED = 1
        # USE DNS NAMES INSTEAD OF FIXED IP ADDRESSES FROM /etc/hosts
        # (see the Userguide "Networking Issues" section).
        Pyro.config.PYRO_DNS_URI = True

        # base (lowest allowed) Pyro socket number
        Pyro.config.PYRO_PORT = base_port
        # max number of sockets starting at base
        Pyro.config.PYRO_PORT_RANGE = max_n_ports

        Pyro.core.initServer()
        self.daemon = Pyro.core.Daemon()
        self.daemon.setAllowedIdentifications( [passphrase(suite,user,get_hostname()).get(suitedir=suitedir)] )
Exemplo n.º 8
0
 def generate( self, dir ):
     pfile = os.path.join(dir, 'passphrase')
     if os.path.isfile( pfile ):
         try:
             self.get( pfile )
             return
         except SecurityError:
             pass
     # Note: Perhaps a UUID might be better here?
     char_set = string.ascii_uppercase + string.ascii_lowercase + string.digits
     self.passphrase = ''.join(random.sample(char_set, 20))
     mkdir_p(dir)
     f = open(pfile, 'w')
     f.write(self.passphrase)
     f.close()
     # set passphrase file permissions to owner-only
     os.chmod( pfile, 0600 )
     if flags.verbose:
         print 'Generated suite passphrase file on', user + '@' + get_hostname() + ':', pfile
Exemplo n.º 9
0
 def generate(self, dir):
     pfile = os.path.join(dir, 'passphrase')
     if os.path.isfile(pfile):
         try:
             self.get(pfile)
             return
         except SecurityError:
             pass
     # Note: Perhaps a UUID might be better here?
     char_set = string.ascii_uppercase + string.ascii_lowercase + string.digits
     self.passphrase = ''.join(random.sample(char_set, 20))
     mkdir_p(dir)
     f = open(pfile, 'w')
     f.write(self.passphrase)
     f.close()
     # set passphrase file permissions to owner-only
     os.chmod(pfile, 0600)
     if self.verbose:
         print 'Generated suite passphrase file on', user + '@' + get_hostname(
         ) + ':', pfile
Exemplo n.º 10
0
    def __init__(self, suite, suitedir, base_port, max_n_ports, user=user):

        self.suite = suite
        self.owner = user

        # SINGLE THREADED PYRO
        Pyro.config.PYRO_MULTITHREADED = 1
        # USE DNS NAMES INSTEAD OF FIXED IP ADDRESSES FROM /etc/hosts
        # (see the Userguide "Networking Issues" section).
        Pyro.config.PYRO_DNS_URI = True

        # base (lowest allowed) Pyro socket number
        Pyro.config.PYRO_PORT = base_port
        # max number of sockets starting at base
        Pyro.config.PYRO_PORT_RANGE = max_n_ports

        Pyro.core.initServer()
        self.daemon = Pyro.core.Daemon()
        self.daemon.setAllowedIdentifications(
            [passphrase(suite, user, get_hostname()).get(suitedir=suitedir)])
Exemplo n.º 11
0
def check_port( suite, pphrase, port, owner=user, host=get_hostname(), pyro_timeout=None ):
    # is a particular suite running at host:port?

    uri = cylcid_uri( host, port )
    proxy = Pyro.core.getProxyForURI(uri)
    if pyro_timeout: # convert from string
        pyro_timeout = float(pyro_timeout)
    proxy._setTimeout(pyro_timeout)

    proxy._setIdentification( pphrase )

    before = datetime.datetime.now()
    try:
        name, xowner = proxy.id()
    except Pyro.errors.TimeoutError:
        warn_timeout( host, port, pyro_timeout )
        raise ConnectionTimedOutError, "ERROR, Connection Timed Out " + portid( host, port )
    except Pyro.errors.ConnectionDeniedError:
        raise ConnectionDeniedError, "ERROR: Connection Denied  at " + portid( host, port )
    except Pyro.errors.ProtocolError:
        raise NoSuiteFoundError, "ERROR: " + suite + " not found at " + portid( host, port )
    except Pyro.errors.NamingError:
        raise OtherServerFoundError, "ERROR: non-cylc pyro server found at " + portid( host, port )
    else:
        if flags.verbose:
            after = datetime.datetime.now()
            print "Pyro connection on port " +str(port) + " took: " + str( after - before )
        if name == suite and xowner == owner:
            # RESULT
            if flags.verbose:
                print suite, owner, host, port
            return True
        else:
            # ID'd some other suite.
            print >> sys.stderr, 'Found ' + name + ' ' + xowner + ' ' + host + ' ' + port
            print >> sys.stderr, ' NOT ' + suite + ' ' + owner + ' ' + host + ' ' + port
            raise OtherSuiteFoundError, "ERROR: Found another suite"
Exemplo n.º 12
0
 def get(self, pfile=None, suitedir=None):
     ppfile = self.get_passphrase_file(pfile, suitedir)
     psf = open(ppfile, 'r')
     lines = psf.readlines()
     psf.close()
     if len(lines) == 0:
         raise InvalidPassphraseError, 'ERROR, passphrase file is empty, on ' + user + '@' + get_hostname(
         ) + ': ' + ppfile
     if len(lines) > 1:
         raise InvalidPassphraseError, 'ERROR, passphrase file contains multiple lines, on ' + user + '@' + get_hostname(
         ) + ': ' + ppfile
     # chomp trailing whitespace and newline
     self.passphrase = lines[0].strip()
     return self.passphrase
Exemplo n.º 13
0
 def __init__(self, suite, owner=user, host=get_hostname(), verbose=False):
     self.suite = suite
     self.owner = owner
     self.host = host
     self.verbose = verbose
     self.location = None
Exemplo n.º 14
0
    def add_std_options(self):
        self.add_option(
            "--user",
            help="Other user account name. This results in " "command reinvocation on the remote account.",
            metavar="USER",
            default=user,
            action="store",
            dest="owner",
        )

        self.add_option(
            "--host",
            help="Other host name. This results in " "command reinvocation on the remote account.",
            metavar="HOST",
            action="store",
            default=get_hostname(),
            dest="host",
        )

        self.add_option(
            "-v", "--verbose", help="Verbose output mode.", action="store_true", default=False, dest="verbose"
        )

        self.add_option(
            "--debug",
            help="Run suites in non-daemon mode, and show exception tracebacks.",
            action="store_true",
            default=False,
            dest="debug",
        )

        self.add_option(
            "--db",
            help="Alternative suite registration database location, " "defaults to $HOME/.cylc/REGDB.",
            metavar="PATH",
            action="store",
            default=None,
            dest="db",
        )

        if self.pyro:
            self.add_option(
                "--port",
                help="Suite port number on the suite host. NOTE: this is retrieved "
                "automatically if passwordless ssh is configured to the suite host.",
                metavar="INT",
                action="store",
                default=None,
                dest="port",
            )

            self.add_option(
                "--use-ssh",
                help="Use ssh to re-invoke the command on the suite host.",
                action="store_true",
                default=False,
                dest="use_ssh",
            )

            self.add_option(
                "--no-login",
                help="Do not use a login shell to run remote ssh commands. " "The default is to use a login shell.",
                action="store_false",
                default=True,
                dest="ssh_login",
            )

            self.add_option(
                "--pyro-timeout",
                metavar="SEC",
                help="Set a timeout for network connections "
                "to the running suite. The default is no timeout. "
                "For task messaging connections see "
                "site/user config file documentation.",
                action="store",
                default=None,
                dest="pyro_timeout",
            )

            if not self.noforce:
                self.add_option(
                    "-f",
                    "--force",
                    help="Do not ask for confirmation before acting. Note that "
                    "it is not necessary to use this option if interactive command "
                    "prompts have been disabled in the site/user config files.",
                    action="store_true",
                    default=False,
                    dest="force",
                )

        if self.jset:
            self.add_option(
                "-s",
                "--set",
                metavar="NAME=VALUE",
                help="Set the value of a Jinja2 template variable in the suite "
                "definition. This option can be used multiple times on the command "
                "line.  WARNING: these settings do not persist across suite restarts; "
                'they need to be set again on the "cylc restart" command line.',
                action="append",
                default=[],
                dest="templatevars",
            )

            self.add_option(
                "--set-file",
                metavar="FILE",
                help="Set the value of Jinja2 template variables in the suite "
                "definition from a file containing NAME=VALUE pairs (one per line). "
                "WARNING: these settings do not persist across suite restarts; "
                'they need to be set again on the "cylc restart" command line.',
                action="store",
                default=None,
                dest="templatevars_file",
            )

        if self.multitask:
            self.add_option(
                "-m",
                "--family",
                help="Match members of named families rather than tasks.",
                action="store_true",
                default=False,
                dest="is_family",
            )
Exemplo n.º 15
0
    def get_passphrase_file( self, pfile=None, suitedir=None ):
        """
Passphrase location, order of preference:

1/ The pfile argument - used for passphrase creation by "cylc register".

2/ The suite definition directory, because suites may be automatically
installed (e.g. by Rose) to remote task hosts, and remote tasks know
this location from their execution environment. Local user command
invocations can use the suite registration database to find the suite
definition directory.  HOWEVER, remote user command invocations cannot
do this even if the local and remote hosts share a common filesystem,
because we cannot be sure if finding the expected suite registration
implies a common filesystem or a different remote suite that happens to
be registered under the same name. User accounts used for remote control
must therefore install the passphrase in the secondary standard
locations (below) or use the command line option to explicitly reveal
the location. Remote tasks with 'ssh messaging = True' look first in the
suite definition directory of the suite host, which they know through
the variable CYLC_SUITE_DEF_PATH_ON_SUITE_HOST in the task execution
environment.

3/ Secondary locations:
    (i) $HOME/.cylc/SUITE_HOST/SUITE_OWNER/SUITE_NAME/passphrase
   (ii) $HOME/.cylc/SUITE_HOST/SUITE_NAME/passphrase
  (iii) $HOME/.cylc/SUITE_NAME/passphrase
These are more sensible locations for remote suite control from accounts
that do not actually need the suite definition directory to be installed.
"""
        # 1/ explicit location given on the command line
        if pfile:
            if os.path.isdir( pfile ):
                # if a directory is given assume the filename
                pfile = os.path.join( pfile, 'passphrase' )
            if os.path.isfile( pfile ):
                self.set_location( pfile )

            else:
                # if an explicit location is given, the file must exist
                raise SecurityError, 'ERROR, file not found on ' + user + '@' + get_hostname() + ': ' + pfile

        # 2/ cylc commands with suite definition directory from local registration
        if not self.location and suitedir:
            pfile = os.path.join( suitedir, 'passphrase' )
            if os.path.isfile( pfile ):
                self.set_location( pfile )

        # (2 before 3 else sub-suites load their parent suite's
        # passphrase on start-up because the "cylc run" command runs in
        # a parent suite task execution environment).

        # 3/ running tasks: suite definition directory (from the task execution environment)
        if not self.location:
            try:
                # Test for presence of task execution environment
                suite_host = os.environ['CYLC_SUITE_HOST']
                suite_owner = os.environ['CYLC_SUITE_OWNER']
            except KeyError:
                # not called by a task
                pass
            else:
                # called by a task
                if is_remote_host( suite_host ) or is_remote_user( suite_owner ):
                    # 2(i)/ cylc messaging calls on a remote account.

                    # First look in the remote suite definition
                    # directory ($CYLC_SUITE_DEF_PATH is modified for
                    # remote tasks):
                    try:
                        pfile = os.path.join( os.environ['CYLC_SUITE_DEF_PATH'], 'passphrase' )
                    except KeyError:
                        pass
                    else:
                        if os.path.isfile( pfile ):
                            self.set_location( pfile )

                else:
                    # 2(ii)/ cylc messaging calls on the suite host and account.

                    # Could be a local task or a remote task with 'ssh
                    # messaging = True'. In either case use
                    # $CYLC_SUITE_DEF_PATH_ON_SUITE_HOST which never
                    # changes, not $CYLC_SUITE_DEF_PATH which gets
                    # modified for remote tasks as described above.
                    try:
                        pfile = os.path.join( os.environ['CYLC_SUITE_DEF_PATH_ON_SUITE_HOST'], 'passphrase' )
                    except KeyError:
                        pass
                    else:
                        if os.path.isfile( pfile ):
                            self.set_location( pfile )

        # 4/ other allowed locations, as documented above
        if not self.location:
            locations = []
            # For remote control commands, self.host here will be fully
            # qualified or not depending on what's given on the command line.
            short_host = re.sub( '\..*', '', self.host )

            locations.append( os.path.join( os.environ['HOME'], '.cylc', self.host, self.owner, self.suite, 'passphrase' ))
            if short_host != self.host:
                locations.append( os.path.join( os.environ['HOME'], '.cylc', short_host, self.owner, self.suite, 'passphrase' ))
            locations.append( os.path.join( os.environ['HOME'], '.cylc', self.host, self.suite, 'passphrase' ))
            if short_host != self.host:
                locations.append( os.path.join( os.environ['HOME'], '.cylc', short_host, self.suite, 'passphrase' ))
            locations.append( os.path.join( os.environ['HOME'], '.cylc', self.suite, 'passphrase' ))
            for pfile in locations:
                if os.path.isfile( pfile ):
                    self.set_location( pfile )
                    break

        if not self.location:
            raise SecurityError, 'ERROR: passphrase for suite ' + self.suite + ' not found on ' + user + '@' + get_hostname()

        return self.location
Exemplo n.º 16
0
    def add_std_options(self):
        self.add_option("--user",
                        help="Other user account name. This results in "
                        "command reinvocation on the remote account.",
                        metavar="USER",
                        default=user,
                        action="store",
                        dest="owner")

        self.add_option("--host",
                        help="Other host name. This results in "
                        "command reinvocation on the remote account.",
                        metavar="HOST",
                        action="store",
                        default=get_hostname(),
                        dest="host")

        self.add_option("-v",
                        "--verbose",
                        help="Verbose output mode.",
                        action="store_true",
                        default=False,
                        dest="verbose")

        self.add_option(
            "--debug",
            help=
            "Run suites in non-daemon mode, and show exception tracebacks.",
            action="store_true",
            default=False,
            dest="debug")

        self.add_option(
            "--db",
            help="Alternative suite registration database location, "
            "defaults to $HOME/.cylc/REGDB.",
            metavar="PATH",
            action="store",
            default=None,
            dest="db")

        if self.pyro:
            self.add_option(
                "--port",
                help=
                "Suite port number on the suite host. NOTE: this is retrieved "
                "automatically if passwordless ssh is configured to the suite host.",
                metavar="INT",
                action="store",
                default=None,
                dest="port")

            self.add_option(
                "--use-ssh",
                help="Use ssh to re-invoke the command on the suite host.",
                action="store_true",
                default=False,
                dest="use_ssh")

            self.add_option(
                "--no-login",
                help="Do not use a login shell to run remote ssh commands. "
                "The default is to use a login shell.",
                action="store_false",
                default=True,
                dest="ssh_login")

            self.add_option("--pyro-timeout",
                            metavar='SEC',
                            help="Set a timeout for network connections "
                            "to the running suite. The default is no timeout. "
                            "For task messaging connections see "
                            "site/user config file documentation.",
                            action="store",
                            default=None,
                            dest="pyro_timeout")

            if not self.noforce:
                self.add_option(
                    "-f",
                    "--force",
                    help="Do not ask for confirmation before acting. Note that "
                    "it is not necessary to use this option if interactive command "
                    "prompts have been disabled in the site/user config files.",
                    action="store_true",
                    default=False,
                    dest="force")

        if self.jset:
            self.add_option(
                "-s",
                "--set",
                metavar="NAME=VALUE",
                help="Set the value of a Jinja2 template variable in the suite "
                "definition. This option can be used multiple times on the command "
                "line.  WARNING: these settings do not persist across suite restarts; "
                "they need to be set again on the \"cylc restart\" command line.",
                action="append",
                default=[],
                dest="templatevars")

            self.add_option(
                "--set-file",
                metavar="FILE",
                help="Set the value of Jinja2 template variables in the suite "
                "definition from a file containing NAME=VALUE pairs (one per line). "
                "WARNING: these settings do not persist across suite restarts; "
                "they need to be set again on the \"cylc restart\" command line.",
                action="store",
                default=None,
                dest="templatevars_file")

        if self.multitask:
            self.add_option(
                "-m",
                "--family",
                help="Match members of named families rather than tasks.",
                action="store_true",
                default=False,
                dest="is_family")
Exemplo n.º 17
0
 def get( self, pfile=None, suitedir=None ):
     ppfile = self.get_passphrase_file( pfile, suitedir )
     psf = open( ppfile, 'r' )
     lines = psf.readlines()
     psf.close()
     if len(lines) == 0:
         raise InvalidPassphraseError, 'ERROR, passphrase file is empty, on ' + user + '@' + get_hostname() + ': ' + ppfile
     if len(lines) > 1:
         raise InvalidPassphraseError, 'ERROR, passphrase file contains multiple lines, on ' + user + '@' + get_hostname() + ': ' + ppfile
     # chomp trailing whitespace and newline
     self.passphrase = lines[0].strip()
     return self.passphrase
Exemplo n.º 18
0
 def __init__(self, suite, owner=user, host=get_hostname()):
     self.suite = suite
     self.owner = owner
     self.host = host
     self.location = None
Exemplo n.º 19
0
 def __init__(self, suite, owner=user, host=get_hostname(), verbose=False):
     self.suite = suite
     self.owner = owner
     self.host = host
     self.verbose = verbose
     self.location = None
Exemplo n.º 20
0
 def set_location(self, pfile):
     if self.verbose:
         print "Passphrase detected at", pfile, "on", user + "@" + get_hostname()
     self.location = pfile
Exemplo n.º 21
0
 def set_location(self, pfile):
     if self.verbose:
         print 'Passphrase detected at', pfile, 'on', user + '@' + get_hostname(
         )
     self.location = pfile
Exemplo n.º 22
0
 def __init__( self, suite, owner=user, host=get_hostname() ):
     self.suite = suite
     self.owner = owner
     self.host = host
     self.location = None
Exemplo n.º 23
0
 def set_location( self, pfile ):
     if flags.verbose:
         print 'Passphrase detected at', pfile, 'on', user + '@' + get_hostname()
     self.location = pfile
Exemplo n.º 24
0
    def get_passphrase_file(self, pfile=None, suitedir=None):
        """
Passphrase location, order of preference:

1/ The pfile argument - used for passphrase creation by "cylc register".

2/ The suite definition directory, because suites may be automatically
installed (e.g. by Rose) to remote task hosts, and remote tasks know
this location from their execution environment. Local user command
invocations can use the suite registration database to find the suite
definition directory.  HOWEVER, remote user command invocations cannot
do this even if the local and remote hosts share a common filesystem,
because we cannot be sure if finding the expected suite registration
implies a common filesystem or a different remote suite that happens to
be registered under the same name. User accounts used for remote control
must therefore install the passphrase in the secondary standard
locations (below) or use the command line option to explicitly reveal
the location. Remote tasks with 'ssh messaging = True' look first in the 
suite definition directory of the suite host, which they know through 
the variable CYLC_SUITE_DEF_PATH_ON_SUITE_HOST in the task execution
environment.

3/ Secondary locations:
    (i) $HOME/.cylc/SUITE_HOST/SUITE_OWNER/SUITE_NAME/passphrase
   (ii) $HOME/.cylc/SUITE_HOST/SUITE_NAME/passphrase
  (iii) $HOME/.cylc/SUITE_NAME/passphrase
These are more sensible locations for remote suite control from accounts
that do not actually need the suite definition directory to be installed.
"""
        # 1/ explicit location given on the command line
        if pfile:
            if os.path.isdir(pfile):
                # if a directory is given assume the filename
                pfile = os.path.join(pfile, 'passphrase')
            if os.path.isfile(pfile):
                self.set_location(pfile)

            else:
                # if an explicit location is given, the file must exist
                raise SecurityError, 'ERROR, file not found on ' + user + '@' + get_hostname(
                ) + ': ' + pfile

        # 2/ cylc commands with suite definition directory from local registration
        if not self.location and suitedir:
            pfile = os.path.join(suitedir, 'passphrase')
            if os.path.isfile(pfile):
                self.set_location(pfile)

        # (2 before 3 else sub-suites load their parent suite's
        # passphrase on start-up because the "cylc run" command runs in
        # a parent suite task execution environment).

        # 3/ running tasks: suite definition directory (from the task execution environment)
        if not self.location:
            try:
                # Test for presence of task execution environment
                suite_host = os.environ['CYLC_SUITE_HOST']
                suite_owner = os.environ['CYLC_SUITE_OWNER']
            except KeyError:
                # not called by a task
                pass
            else:
                # called by a task
                if is_remote_host(suite_host) or is_remote_user(suite_owner):
                    # 2(i)/ cylc messaging calls on a remote account.

                    # First look in the remote suite definition
                    # directory ($CYLC_SUITE_DEF_PATH is modified for
                    # remote tasks):
                    try:
                        pfile = os.path.join(os.environ['CYLC_SUITE_DEF_PATH'],
                                             'passphrase')
                    except KeyError:
                        pass
                    else:
                        if os.path.isfile(pfile):
                            self.set_location(pfile)

                else:
                    # 2(ii)/ cylc messaging calls on the suite host and account.

                    # Could be a local task or a remote task with 'ssh
                    # messaging = True'. In either case use
                    # $CYLC_SUITE_DEF_PATH_ON_SUITE_HOST which never
                    # changes, not $CYLC_SUITE_DEF_PATH which gets
                    # modified for remote tasks as described above.
                    try:
                        pfile = os.path.join(
                            os.environ['CYLC_SUITE_DEF_PATH_ON_SUITE_HOST'],
                            'passphrase')
                    except KeyError:
                        pass
                    else:
                        if os.path.isfile(pfile):
                            self.set_location(pfile)

        # 4/ other allowed locations, as documented above
        if not self.location:
            locations = []
            # For remote control commands, self.host here will be fully
            # qualified or not depending on what's given on the command line.
            short_host = re.sub('\..*', '', self.host)

            locations.append(
                os.path.join(os.environ['HOME'], '.cylc', self.host,
                             self.owner, self.suite, 'passphrase'))
            if short_host != self.host:
                locations.append(
                    os.path.join(os.environ['HOME'], '.cylc', short_host,
                                 self.owner, self.suite, 'passphrase'))
            locations.append(
                os.path.join(os.environ['HOME'], '.cylc', self.host,
                             self.suite, 'passphrase'))
            if short_host != self.host:
                locations.append(
                    os.path.join(os.environ['HOME'], '.cylc', short_host,
                                 self.suite, 'passphrase'))
            locations.append(
                os.path.join(os.environ['HOME'], '.cylc', self.suite,
                             'passphrase'))
            for pfile in locations:
                if os.path.isfile(pfile):
                    self.set_location(pfile)
                    break

        if not self.location:
            raise SecurityError, 'ERROR: passphrase for suite ' + self.suite + ' not found on ' + user + '@' + get_hostname(
            )

        return self.location