Exemplo n.º 1
0
def main():
    """rose task-env."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("cycle", "cycle_offsets", "path_globs",
                              "prefix_delim", "suffix_delim")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness - 1)
    suite_engine_proc = SuiteEngineProcessor.get_processor(
        event_handler=report)
    kwargs = dict(vars(opts))
    try:
        task_props = suite_engine_proc.get_task_props(*args, **kwargs)
        for key, value in task_props:
            report(str(EnvExportEvent(key, value)) + "\n", level=0)
        path_globs = opts.path_globs
        if path_globs is None:
            path_globs = []
        prepend_paths_map = get_prepend_paths(report,
                                              task_props.suite_dir,
                                              path_globs,
                                              full_mode=True)
        for key, prepend_paths in prepend_paths_map.items():
            orig_paths = []
            orig_v = os.getenv(key, "")
            if orig_v:
                orig_paths = orig_v.split(os.pathsep)
            path = os.pathsep.join(prepend_paths + orig_paths)
            report(str(EnvExportEvent(key, path)) + "\n", level=0)
    except Exception as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)
Exemplo n.º 2
0
    def _find_vc_file_from_location(location):
        """Search a location and parents for a version control log file.

        Args:
            location: Path to search.

        Returns:
            If a file is found, a path, else None.
        """
        suite_engine_proc = SuiteEngineProcessor.get_processor()
        suite_dir_rel_root = getattr(suite_engine_proc, "SUITE_DIR_REL_ROOT",
                                     None)
        loc = Path(location).expanduser().resolve()
        if suite_dir_rel_root:
            sdrr = Path('~', suite_dir_rel_root).expanduser().resolve()
            try:
                loc.relative_to(sdrr)
            except ValueError:
                # Not an installed Cylc8 workflow run directory
                pass
            else:
                # Slightly odd construction = loc + parents
                for loc in (loc.relative_to(sdrr) / '_').parents:
                    vcfilepath = sdrr / loc / SuiteId.VC_FILENAME
                    if os.access(vcfilepath, os.F_OK | os.R_OK):
                        return vcfilepath
        return None
Exemplo n.º 3
0
def main():
    """Implement "rose suite-hook" command."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("mail_cc", "mail", "retrieve_job_logs",
                              "shutdown")
    opts, args = opt_parser.parse_args()
    for key in ["mail_cc"]:
        values = []
        if getattr(opts, key):
            for value in getattr(opts, key):
                values.extend(value.split(","))
        setattr(opts, key, values)
    report = Reporter(opts.verbosity - opts.quietness - 1)  # Reduced default
    popen = RosePopener(event_handler=report)
    suite_engine_proc = SuiteEngineProcessor.get_processor(
        event_handler=report, popen=popen)
    args = suite_engine_proc.process_suite_hook_args(*args, **vars(opts))
    hook = RoseSuiteHook(event_handler=report,
                         popen=popen,
                         suite_engine_proc=suite_engine_proc)
    hook(*args,
         should_mail=opts.mail,
         mail_cc_list=opts.mail_cc,
         should_shutdown=opts.shutdown,
         should_retrieve_job_logs=opts.retrieve_job_logs)
Exemplo n.º 4
0
 def __init__(
     self,
     event_handler=None,
     popen=None,
     config_pm=None,
     fs_util=None,
     suite_engine_proc=None,
 ):
     if not self.CONF_NAME:
         self.CONF_NAME = self.NAME
     self.event_handler = event_handler
     if popen is None:
         popen = RosePopener(event_handler)
     self.popen = popen
     if fs_util is None:
         fs_util = FileSystemUtil(event_handler)
     self.fs_util = fs_util
     if config_pm is None:
         config_pm = ConfigProcessorsManager(event_handler, popen, fs_util)
     self.config_pm = config_pm
     if suite_engine_proc is None:
         suite_engine_proc = SuiteEngineProcessor.get_processor(
             event_handler=event_handler, popen=popen, fs_util=fs_util
         )
     self.suite_engine_proc = suite_engine_proc
     self.conf_tree_loader = ConfigTreeLoader()
Exemplo n.º 5
0
 def __init__(self, event_handler=None, popen=None, suite_engine_proc=None):
     self.event_handler = event_handler
     if popen is None:
         popen = RosePopener(event_handler)
     self.popen = popen
     if suite_engine_proc is None:
         suite_engine_proc = SuiteEngineProcessor.get_processor(
             event_handler=event_handler, popen=popen)
     self.suite_engine_proc = suite_engine_proc
Exemplo n.º 6
0
 def __init__(self,
              event_handler=None,
              host_selector=None,
              suite_engine_proc=None):
     if event_handler is None:
         event_handler = Reporter()
     self.event_handler = event_handler
     if host_selector is None:
         host_selector = HostSelector(event_handler=event_handler)
     self.host_selector = host_selector
     if suite_engine_proc is None:
         suite_engine_proc = SuiteEngineProcessor.get_processor(
             event_handler=event_handler)
     self.suite_engine_proc = suite_engine_proc
Exemplo n.º 7
0
def suite_log_view(opts, args, event_handler=None):
    """Implement "rose suite-log" CLI functionality."""
    suite_engine_proc = SuiteEngineProcessor.get_processor(
        event_handler=event_handler)
    opts.update_mode = (
        opts.update_mode or opts.archive_mode or opts.force_mode)
    if opts.force_mode:
        args = ["*"]
    if not opts.name:
        opts.name = get_suite_name(event_handler)
        if not opts.update_mode and not opts.user:
            opts.user = pwd.getpwuid(os.stat(".").st_uid).pw_name
    if opts.archive_mode:
        suite_engine_proc.job_logs_archive(opts.name, args)
    elif opts.update_mode:
        suite_engine_proc.job_logs_pull_remote(
            opts.name, args, opts.prune_remote_mode, opts.force_mode)
    if opts.view_mode or not opts.update_mode:
        n_tries_left = 1
        is_rose_bush_started = False
        url = suite_engine_proc.get_suite_log_url(opts.user, opts.name)
        if url.startswith("file://"):
            if (opts.non_interactive or
                    input(
                        "Start rose bush? [y/n] (default=n) ") == "y"):
                suite_engine_proc.popen.run_bg(
                    "rose", "bush", "start", preexec_fn=os.setpgrp)
                is_rose_bush_started = True
                n_tries_left = 5  # Give the server a chance to start
        while n_tries_left:
            n_tries_left -= 1
            if n_tries_left:
                url = suite_engine_proc.get_suite_log_url(opts.user, opts.name)
                if url.startswith("file://"):
                    sleep(1)
                    continue
            suite_engine_proc.launch_suite_log_browser(opts.user, opts.name)
            break
        if is_rose_bush_started:
            status = suite_engine_proc.popen("rose", "bush")[0]
            event_handler(RoseBushStartEvent(status))
    return
Exemplo n.º 8
0
 def __init__(self, *args, **kwargs):
     SuiteEngineProcessor.__init__(self, *args, **kwargs)
     self.daos = {}
     self.host = None
     self.user = None
Exemplo n.º 9
0
    def _from_location(self, location):
        """Return the ID of a location (origin URL or local copy path)."""
        suite_engine_proc = SuiteEngineProcessor.get_processor()
        suite_dir_rel_root = getattr(suite_engine_proc, "SUITE_DIR_REL_ROOT",
                                     None)

        # Cylc8 run directory
        # TODO: extract version control information
        loc = Path(location)
        sdrr = Path('~', suite_dir_rel_root).expanduser().resolve()
        try:
            loc.relative_to(sdrr)
        except ValueError:
            # Not an installed Cylc8 workflow run directory
            pass
        else:
            if (loc / 'rose-suite.info').is_file():
                # This is an installed workflow with a rose-suite.info file
                # (most likely a Cylc8 run directory)

                # TODO: extract version control information written by
                # Cylc install, see:
                # https://github.com/metomi/rose/issues/2432
                # https://github.com/cylc/cylc-flow/issues/3849
                raise SuiteIdLocationError(location)

        # Cylc7 run directory
        # Use a hacky way to read the "log/rose-suite-run.version" file
        suite_dir_rel_root = getattr(suite_engine_proc, "SUITE_DIR_REL_ROOT",
                                     None)
        if suite_dir_rel_root and "/" + suite_dir_rel_root + "/" in location:
            loc = location
            while "/" + suite_dir_rel_root + "/" in loc:
                suite_version_file_name = os.path.join(
                    loc, "log/rose-suite-run.version")
                loc = os.path.dirname(loc)
                if not os.access(suite_version_file_name, os.F_OK | os.R_OK):
                    continue
                state = None
                url = None
                rev = None
                for line in open(suite_version_file_name):
                    line = line.strip()
                    if state is None:
                        if line.startswith("# svn info"):
                            state = line
                    elif state.startswith("# svn info"):
                        if line.startswith("URL:"):
                            url = line.split(":", 1)[1].strip()
                        elif line.startswith("Revision:"):
                            rev = line.split(":", 1)[1].strip()
                        elif not line:
                            break
                if url and rev:
                    location = url + "@" + rev
                break

        # Assume location is a Subversion working copy of a Rosie suite
        info_parser = SvnInfoXMLParser()
        try:
            info_entry = info_parser.parse(self.svn("info", "--xml", location))
        except RosePopenError:
            raise SuiteIdLocationError(location)

        if "url" not in info_entry:
            raise SuiteIdLocationError(location)
        root = info_entry["repository:root"]
        url = info_entry["url"]
        path = url[len(root):]
        if not path:
            raise SuiteIdLocationError(location)
        self.prefix = self.get_prefix_from_location_root(root)
        names = path.lstrip("/").split("/", self.SID_LEN + 1)
        if len(names) < self.SID_LEN:
            raise SuiteIdLocationError(location)
        sid = "".join(names[0:self.SID_LEN])
        if not self.REC_IDX.match(sid):
            raise SuiteIdLocationError(location)
        self.idx = self.FORMAT_IDX % (self.prefix, sid)
        self.sid = sid
        if len(names) > self.SID_LEN:
            self.branch = names[self.SID_LEN]
        if "commit:revision" in info_entry:
            self.revision = info_entry["commit:revision"]
Exemplo n.º 10
0
 def __init__(self, event_handler=None):
     self.event_handler = event_handler
     self.popen = RosePopener(self.event_handler)
     self.suite_engine_proc = SuiteEngineProcessor.get_processor(
         event_handler=self.event_handler, popen=self.popen)
Exemplo n.º 11
0
def main():
    """rose task-env."""
    opt_parser = RoseOptionParser(
        description='''
STANDARD USAGE:
    eval $(rose task-env)

Provide an environment for cycling suite task.

Print `KEY=VALUE` of the following to the STDOUT:

`ROSE_SUITE_DIR`
    The path to the root directory of the running suite.
`ROSE_SUITE_DIR_REL`
    The path to the root directory of the running suite relative to
    `$HOME`.
`ROSE_SUITE_NAME`
    The name of the running suite.
`ROSE_TASK_NAME`
    The name of the suite task.
`ROSE_TASK_CYCLE_TIME`
    The cycle time of the suite task, if there is one.
`ROSE_CYCLING_MODE`
    The cycling mode of the running suite.
`ROSE_TASK_LOG_ROOT`
    The root path for log files of the suite task.
`ROSE_DATA`
    The path to the data directory of the running suite.
`ROSE_DATAC`
    The path to the data directory of this cycle
    time in the running suite.
`ROSE_DATAC????`
    The path to the data directory of the cycle time with an offset
    relative to the current cycle time. `????` is a duration:

    A `__` (double underscore) prefix denotes a cycle time in the
    future (because a minus sign cannot be used in an environment
    variable). Otherwise, it is a cycle time in the past.

    The rest should be either an ISO 8601 duration, such as:

    * `P2W` - 2 weeks
    * `PT12H` - 12 hours
    * `P1DT6H` - 1 day, 6 hours
    * `P4M` - 4 months
    * `PT5M` - 5 minutes

    Or, for the case of integer cycling suites:

    * `P1` - 1 cycle before the current cycle
    * `P5` - 5 cycles before the current cycle

    Deprecated syntax:

    * `nW` denotes `n` weeks.
    * `n` or `nD` denotes `n` days.
    * `Tn` or `TnH` denotes `n` hours.
    * `TnM` denotes `n` minutes.
    * `TnS` denotes `s` seconds.

    E.g. `ROSE_DATACPT6H` is the data directory of 6 hours before the
    current cycle time.

    E.g. `ROSE_DATACP1D` and `ROSE_DATACPT24H` are both the data
    directory of 1 day before the current cycle time.
`ROSE_ETC`
    The path to the etc directory of the running suite.
`ROSE_TASK_PREFIX`
    The prefix in the task name.
`ROSE_TASK_SUFFIX`
    The suffix in the task name.
        ''',
        epilog='''
USAGE IN SUITES
    rose `task-env` can be used to make environment variables available to a
    suite by defining its `flow.cylc` `env-script` option as
    `env-script = eval $(rose task-env)`.
        ''',
    )
    opt_parser.add_my_options("cycle", "cycle_offsets", "path_globs",
                              "prefix_delim", "suffix_delim")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness - 1)
    suite_engine_proc = SuiteEngineProcessor.get_processor(
        event_handler=report)
    kwargs = dict(vars(opts))
    try:
        task_props = suite_engine_proc.get_task_props(*args, **kwargs)
        for key, value in task_props:
            report(str(EnvExportEvent(key, value)) + "\n", level=0)
        path_globs = opts.path_globs
        if path_globs is None:
            path_globs = []
        prepend_paths_map = get_prepend_paths(report,
                                              task_props.suite_dir,
                                              path_globs,
                                              full_mode=True)
        for key, prepend_paths in prepend_paths_map.items():
            orig_paths = []
            orig_v = os.getenv(key, "")
            if orig_v:
                orig_paths = orig_v.split(os.pathsep)
            path = os.pathsep.join(prepend_paths + orig_paths)
            report(str(EnvExportEvent(key, path)) + "\n", level=0)
    except Exception as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)
Exemplo n.º 12
0
 def __init__(self, event_handler=None):
     self.event_handler = event_handler
     self.suite_engine_proc = SuiteEngineProcessor.get_processor(
         event_handler=event_handler)
Exemplo n.º 13
0
 def to_output(self):
     """Return the output directory for this suite."""
     suite_engine_proc = SuiteEngineProcessor.get_processor()
     return suite_engine_proc.get_suite_log_url(None, str(self))
Exemplo n.º 14
0
    def _from_location(self, location):
        """Return the ID of a location (origin URL or local copy path)."""
        # Is location a "~/cylc-run/$SUITE/" directory?
        # Use a hacky way to read the "log/rose-suite-run.version" file
        suite_engine_proc = SuiteEngineProcessor.get_processor()
        suite_dir_rel_root = getattr(suite_engine_proc, "SUITE_DIR_REL_ROOT",
                                     None)
        if suite_dir_rel_root and "/" + suite_dir_rel_root + "/" in location:
            loc = location
            while "/" + suite_dir_rel_root + "/" in loc:
                suite_version_file_name = os.path.join(
                    loc, "log/rose-suite-run.version")
                loc = os.path.dirname(loc)
                if not os.access(suite_version_file_name, os.F_OK | os.R_OK):
                    continue
                state = None
                url = None
                rev = None
                for line in open(suite_version_file_name):
                    line = line.strip()
                    if state is None:
                        if line.startswith("# svn info"):
                            state = line
                    elif state.startswith("# svn info"):
                        if line.startswith("URL:"):
                            url = line.split(":", 1)[1].strip()
                        elif line.startswith("Revision:"):
                            rev = line.split(":", 1)[1].strip()
                        elif not line:
                            break
                if url and rev:
                    location = url + "@" + rev
                break

        # Assume location is a Subversion working copy of a Rosie suite
        info_parser = SvnInfoXMLParser()
        try:
            info_entry = info_parser.parse(self.svn("info", "--xml", location))
        except RosePopenError:
            raise SuiteIdLocationError(location)

        if "url" not in info_entry:
            raise SuiteIdLocationError(location)
        root = info_entry["repository:root"]
        url = info_entry["url"]
        path = url[len(root):]
        if not path:
            raise SuiteIdLocationError(location)
        self.prefix = self.get_prefix_from_location_root(root)
        names = path.lstrip("/").split("/", self.SID_LEN + 1)
        if len(names) < self.SID_LEN:
            raise SuiteIdLocationError(location)
        sid = "".join(names[0:self.SID_LEN])
        if not self.REC_IDX.match(sid):
            raise SuiteIdLocationError(location)
        self.idx = self.FORMAT_IDX % (self.prefix, sid)
        self.sid = sid
        if len(names) > self.SID_LEN:
            self.branch = names[self.SID_LEN]
        if "commit:revision" in info_entry:
            self.revision = info_entry["commit:revision"]