コード例 #1
0
ファイル: test_httpclient.py プロジェクト: shishakt/cylc
 def test_compile_url_compiler_http(self):
     """Test that the url compiler produces a http request when
     http is specified."""
     myclient = SuiteRuntimeServiceClient("test-suite",
                                          host=get_host(),
                                          port=80)
     myclient.comms1[SuiteSrvFilesManager.KEY_COMMS_PROTOCOL] = 'http'
     self.assertEqual(
         'http://%s:80/test_command?apples=False&oranges=True' % get_host(),
         myclient._call_server_get_url("test_command",
                                       apples="False",
                                       oranges="True"))
コード例 #2
0
ファイル: test_httpclient.py プロジェクト: shishakt/cylc
 def test_url_compiler_https(self):
     """Tests that the url parser works for a single url and command
     using https"""
     myclient = SuiteRuntimeServiceClient("test-suite",
                                          host=get_host(),
                                          port=80)
     myclient.comms1[SuiteSrvFilesManager.KEY_COMMS_PROTOCOL] = 'https'
     self.assertEqual(
         'https://%s:80/test_command?apples=False&oranges=True' %
         get_host(),
         myclient._call_server_get_url("test_command",
                                       apples="False",
                                       oranges="True"))
コード例 #3
0
ファイル: test_httpclient.py プロジェクト: shishakt/cylc
 def test_compile_url_compiler_none_specified(self):
     """Test that the url compiler produces a http request when
     none is specified. This should retrieve it from the
     global config."""
     myclient = SuiteRuntimeServiceClient("test-suite",
                                          host=get_host(),
                                          port=80)
     url = myclient._call_server_get_url("test_command",
                                         apples="False",
                                         oranges="True")
     # Check that the url has had http (or https) appended
     # to it. (If it does not start with "http*" then something
     # has gone wrong.)
     self.assertTrue(url.startswith("http"))
コード例 #4
0
ファイル: port_scan.py プロジェクト: andymoorhouse/cylc
def _scan_item(timeout, my_uuid, srv_files_mgr, item):
    """Connect to item host:port (item) to get suite identify."""
    host, port = item
    host_anon = host
    if is_remote_host(host):
        try:
            host_anon = get_host_ip_by_name(host)  # IP reduces DNS traffic
        except socket.error as exc:
            if cylc.flags.debug:
                raise
            sys.stderr.write("ERROR: %s: %s\n" % (exc, host))
            return (host, port, None)

    client = SuiteRuntimeServiceClient(
        None,
        host=host_anon,
        port=port,
        my_uuid=my_uuid,
        timeout=timeout,
        auth=SuiteRuntimeServiceClient.ANON_AUTH)
    try:
        result = client.identify()
    except ClientTimeout:
        return (host, port, MSG_TIMEOUT)
    except ClientError:
        return (host, port, None)
    else:
        owner = result.get(KEY_OWNER)
        name = result.get(KEY_NAME)
        states = result.get(KEY_STATES, None)
        if cylc.flags.debug:
            sys.stderr.write('   suite: %s %s\n' % (name, owner))
        if states is None:
            # This suite keeps its state info private.
            # Try again with the passphrase if I have it.
            try:
                pphrase = srv_files_mgr.get_auth_item(
                    srv_files_mgr.FILE_BASE_PASSPHRASE,
                    name,
                    owner,
                    host,
                    content=True)
            except SuiteServiceFileError:
                pass
            else:
                if pphrase:
                    client.suite = name
                    client.owner = owner
                    client.auth = None
                    try:
                        result = client.identify()
                    except ClientError:
                        # Nope (private suite, wrong passphrase).
                        if cylc.flags.debug:
                            sys.stderr.write('    (wrong passphrase)\n')
                    else:
                        if cylc.flags.debug:
                            sys.stderr.write(
                                '    (got states with passphrase)\n')
        return (host, port, result)
コード例 #5
0
    def _send_by_remote_port(self, messages):
        """Send message by talking to the daemon (remote?) port."""
        from cylc.network.httpclient import (SuiteRuntimeServiceClient,
                                             ClientError, ClientInfoError)

        # Convert time/duration into appropriate units
        retry_intvl = float(
            self.env_map.get(SuiteSrvFilesManager.KEY_TASK_MSG_RETRY_INTVL,
                             self.MSG_RETRY_INTVL))
        max_tries = int(
            self.env_map.get(SuiteSrvFilesManager.KEY_TASK_MSG_MAX_TRIES,
                             self.MSG_MAX_TRIES))

        client = SuiteRuntimeServiceClient(
            self.suite,
            owner=self.env_map.get(SuiteSrvFilesManager.KEY_OWNER),
            host=self.env_map.get(SuiteSrvFilesManager.KEY_HOST),
            port=self.env_map.get(SuiteSrvFilesManager.KEY_PORT),
            timeout=float(
                self.env_map.get(SuiteSrvFilesManager.KEY_TASK_MSG_TIMEOUT,
                                 self.MSG_TIMEOUT)),
            comms_protocol=self.env_map.get(
                SuiteSrvFilesManager.KEY_COMMS_PROTOCOL))
        for i in range(1, max_tries + 1):  # 1..max_tries inclusive
            try:
                for message in messages:
                    client.put_message(self.task_id, self.severity, message)
            except ClientError as exc:
                sys.stderr.write(
                    "%s WARNING - Send message: try %s of %s failed: %s\n" %
                    (get_current_time_string(), i, max_tries, exc))
                # Break if:
                # * Exhausted number of tries.
                # * Contact info file not found, suite probably not running.
                #   Don't bother with retry, suite restart will poll any way.
                if i >= max_tries or isinstance(exc, ClientInfoError):
                    # Issue a warning and let the task carry on
                    sys.stderr.write("%s WARNING - MESSAGE SEND FAILED\n" %
                                     (get_current_time_string()))
                else:
                    sys.stderr.write(
                        "   retry in %s seconds, timeout is %s\n" %
                        (retry_intvl, client.timeout))
                    sleep(retry_intvl)
                    # Reset in case contact info or passphrase change
                    client.host = None
                    client.port = None
                    client.auth = None
            else:
                if i > 1:
                    # Continue to write to STDERR, so users can easily see that
                    # it has recovered from previous failures.
                    sys.stderr.write(
                        "%s INFO - Send message: try %s of %s succeeded\n" %
                        (get_current_time_string(), i, max_tries))
                break
コード例 #6
0
ファイル: task_message.py プロジェクト: shishakt/cylc
def record_messages(suite, task_job, messages):
    """Record task job messages.

    Print the messages according to their severity.
    Write the messages in the job status file.
    Send the messages to the suite, if possible.

    Arguments:
        suite (str): Suite name.
        task_job (str): Task job identifier "CYCLE/TASK_NAME/SUBMIT_NUM".
        messages (list): List of messages "[[severity, message], ...]".
    """
    # Record the event time, in case the message is delayed in some way.
    event_time = get_current_time_string(
        override_use_utc=(os.getenv('CYLC_UTC') == 'True'))
    # Print to stdout/stderr
    for severity, message in messages:
        if severity in STDERR_LEVELS:
            handle = sys.stderr
        else:
            handle = sys.stdout
        handle.write('%s %s - %s\n' % (event_time, severity, message))
    handle.flush()
    # Write to job.status
    _append_job_status_file(suite, task_job, event_time, messages)
    # Send messages
    client = SuiteRuntimeServiceClient(suite)
    try:
        client.put_messages({
            'task_job': task_job,
            'event_time': event_time,
            'messages': messages
        })
    except ClientInfoError:
        # Backward communication not possible
        if cylc.flags.debug:
            import traceback
            traceback.print_exc()
コード例 #7
0
ファイル: task_message.py プロジェクト: arjclark/cylc
def record_messages(suite, task_job, messages):
    """Record task job messages.

    Print the messages according to their severity.
    Write the messages in the job status file.
    Send the messages to the suite, if possible.

    Arguments:
        suite (str): Suite name.
        task_job (str): Task job identifier "CYCLE/TASK_NAME/SUBMIT_NUM".
        messages (list): List of messages "[[severity, message], ...]".
    """
    # Record the event time, in case the message is delayed in some way.
    event_time = get_current_time_string(
        override_use_utc=(os.getenv('CYLC_UTC') == 'True'))
    # Print to stdout/stderr
    for severity, message in messages:
        if severity in STDERR_LEVELS:
            handle = sys.stderr
        else:
            handle = sys.stdout
        handle.write('%s %s - %s\n' % (event_time, severity, message))
    handle.flush()
    # Write to job.status
    _append_job_status_file(suite, task_job, event_time, messages)
    # Send messages
    client = SuiteRuntimeServiceClient(suite)
    try:
        client.put_messages({
            'task_job': task_job,
            'event_time': event_time,
            'messages': messages})
    except ClientInfoError:
        # Backward communication not possible
        if cylc.flags.debug:
            import traceback
            traceback.print_exc()
コード例 #8
0
ファイル: port_scan.py プロジェクト: arjclark/cylc
def _scan_item(timeout, my_uuid, srv_files_mgr, item):
    """Connect to item host:port (item) to get suite identify."""
    host, port = item
    host_anon = host
    if is_remote_host(host):
        host_anon = get_host_ip_by_name(host)  # IP reduces DNS traffic
    client = SuiteRuntimeServiceClient(
        None, host=host_anon, port=port, my_uuid=my_uuid,
        timeout=timeout, auth=SuiteRuntimeServiceClient.ANON_AUTH)
    try:
        result = client.identify()
    except ClientTimeout:
        return (host, port, MSG_TIMEOUT)
    except ClientError:
        return (host, port, None)
    else:
        owner = result.get(KEY_OWNER)
        name = result.get(KEY_NAME)
        states = result.get(KEY_STATES, None)
        if cylc.flags.debug:
            sys.stderr.write('   suite: %s %s\n' % (name, owner))
        if states is None:
            # This suite keeps its state info private.
            # Try again with the passphrase if I have it.
            try:
                pphrase = srv_files_mgr.get_auth_item(
                    srv_files_mgr.FILE_BASE_PASSPHRASE,
                    name, owner, host, content=True)
            except SuiteServiceFileError:
                pass
            else:
                if pphrase:
                    client.suite = name
                    client.owner = owner
                    client.auth = None
                    try:
                        result = client.identify()
                    except ClientError:
                        # Nope (private suite, wrong passphrase).
                        if cylc.flags.debug:
                            sys.stderr.write('    (wrong passphrase)\n')
                    else:
                        if cylc.flags.debug:
                            sys.stderr.write(
                                '    (got states with passphrase)\n')
        return (host, port, result)
コード例 #9
0
ファイル: updater.py プロジェクト: ivorblockley/cylc
class Updater(threading.Thread):

    """Retrieve information about the running or stopped suite."""

    def __init__(self, app):

        super(Updater, self).__init__()

        self.quit = False

        self.app_window = app.window
        self.cfg = app.cfg
        self.info_bar = app.info_bar
        self.full_mode = True

        self.err_log_lines = []
        self.task_list = []

        self.state_summary = {}
        self.full_state_summary = {}
        self.fam_state_summary = {}
        self.full_fam_state_summary = {}
        self.all_families = {}
        self.global_summary = {}
        self.ancestors = {}
        self.ancestors_pruned = {}
        self.descendants = {}
        self.stop_summary = None

        self.mode = "waiting..."
        self.update_time_str = "waiting..."
        self.last_update_time = time()
        self.update_interval = 1.0
        self.max_update_interval = gcfg.get(['maximum update interval'])
        self.status = SUITE_STATUS_NOT_CONNECTED
        self.is_reloading = False
        self.connected = False
        self.no_update_event = threading.Event()
        self.ns_defn_order = []
        self.dict_ns_defn_order = {}
        self.restricted_display = app.restricted_display
        self.filter_name_string = ''
        self.filter_states_excl = []
        self.kept_task_ids = set()
        self.filt_task_ids = set()

        self.version_mismatch_warned = False

        self.client = None
        # Report sign-out on exit.
        atexit.register(self.signout)

    def signout(self):
        """Sign out the client, if possible."""
        if self.client is not None:
            try:
                self.client.signout()
            except ClientError:
                pass

    def set_stopped(self):
        """Reset data and clients when suite is stopped."""
        if cylc.flags.debug:
            sys.stderr.write("%s NOT CONNECTED\n" % get_current_time_string())
        self.full_mode = True
        self.connected = False
        self.set_status(SUITE_STATUS_STOPPED)
        self.update_interval += 1.0
        if self.update_interval > self.max_update_interval:
            self.update_interval = self.max_update_interval
        self.state_summary = {}
        self.full_state_summary = {}
        self.fam_state_summary = {}
        self.full_fam_state_summary = {}
        self.all_families = {}
        self.global_summary = {}
        self.cfg.port = None
        self.client = None

        gobject.idle_add(self.app_window.set_title, str(self.cfg.suite))

        # Use info bar to display stop summary if available.
        # Otherwise, just display the reconnect count down.
        if self.cfg.suite and self.stop_summary is None:
            stop_summary = get_stop_state_summary(
                cat_state(self.cfg.suite, self.cfg.host, self.cfg.owner))
            if stop_summary != self.stop_summary:
                self.stop_summary = stop_summary
                self.status = SUITE_STATUS_STOPPED
                gobject.idle_add(
                    self.info_bar.set_stop_summary, stop_summary)
                self.last_update_time = time()
        try:
            update_time_str = time2str(self.stop_summary[0]["last_updated"])
        except (AttributeError, IndexError, KeyError, TypeError):
            update_time_str = None
        gobject.idle_add(
            self.info_bar.set_update_time,
            update_time_str, self.info_bar.DISCONNECTED_TEXT)
        gobject.idle_add(self.info_bar.prog_bar_stop)

    def set_status(self, status=None):
        """Update status bar."""
        if status == self.status:
            return
        if status is not None:
            self.status = status
        gobject.idle_add(self.info_bar.set_status, self.status)

    def warn(self, msg):
        """Pop up a warning dialog; call on idle_add!"""
        warning_dialog(msg, self.info_bar.get_toplevel()).warn()
        return False

    def filter_by_name(self, states):
        """Filter by name string."""
        return dict(
            (i, j) for i, j in states.items() if
            self.filter_name_string in j['name'] or
            re.search(self.filter_name_string, j['name']))

    def filter_by_state(self, states):
        """Filter by state key."""
        return dict(
            (i, j) for i, j in states.items() if
            j['state'] not in self.filter_states_excl)

    def filter_families(self, families):
        """Remove family summaries if no members are present."""
        fam_states = {}
        for fam_id, summary in families.items():
            name, point_string = TaskID.split(fam_id)
            for mem in self.descendants[name]:
                mem_id = TaskID.get(mem, point_string)
                if mem_id in self.state_summary:
                    fam_states[fam_id] = summary
                    break
        return fam_states

    @classmethod
    def filter_for_restricted_display(cls, states):
        """Filter for legal restricted states."""
        return dict((i, j) for i, j in states.items() if
                    j['state'] in TASK_STATUSES_RESTRICTED)

    def refilter(self):
        """filter from the full state summary"""
        if self.filter_name_string or self.filter_states_excl:
            states = self.full_state_summary
            all_ids = set(states.keys())
            if self.filter_name_string:
                states = self.filter_by_name(states)
            if self.filter_states_excl:
                states = self.filter_by_state(states)
            self.state_summary = states
            fam_states = self.full_fam_state_summary
            self.fam_state_summary = self.filter_families(fam_states)
            self.kept_task_ids = set(states.keys())
            self.filt_task_ids = all_ids - self.kept_task_ids
        else:
            self.state_summary = self.full_state_summary
            self.fam_state_summary = self.full_fam_state_summary
            self.filt_task_ids = set()
            self.kept_task_ids = set(self.state_summary)
        self.task_list = list(
            set(t['name'] for t in self.state_summary.values()))
        self.task_list.sort()

    def stop(self):
        """Tell self.run to exit."""
        self.quit = True

    def run(self):
        """Start the thread."""
        prev_update_time = time()
        while not self.quit:
            now = time()
            if self.no_update_event.is_set():
                pass
            elif now > prev_update_time + self.update_interval:
                self.update()
                prev_update_time = time()
            else:
                duration = round(prev_update_time + self.update_interval - now)
                if self.update_interval >= self.max_update_interval:
                    self.info_bar.set_update_time(None, duration2str(duration))
            sleep(1)

    def update(self):
        """Call suite for an update."""
        if self.client is None:
            self.client = SuiteRuntimeServiceClient(
                self.cfg.suite, self.cfg.owner, self.cfg.host, self.cfg.port,
                self.cfg.comms_timeout, self.cfg.my_uuid)
        try:
            my_state = self.client.get_latest_state(full_mode=self.full_mode)
        except ClientError:
            # Bad credential, suite not running, starting up or just stopped?
            if cylc.flags.debug:
                try:
                    traceback.print_exc()
                except IOError:
                    pass  # Cannot print to terminal (session may be closed).
            self.set_stopped()
            return
        # OK
        if cylc.flags.debug:
            sys.stderr.write("%s CONNECTED - suite cylc version=%s\n" % (
                get_current_time_string(), my_state['cylc_version']))
        self.info_bar.set_update_time(None, None)
        if my_state['full_mode']:
            gobject.idle_add(
                self.app_window.set_title, "%s - %s:%s" % (
                    self.cfg.suite, self.client.host, self.client.port))
            # Connected.
            self.full_mode = False
            self.connected = True
            # This status will be very transient:
            self.set_status(SUITE_STATUS_CONNECTED)

            if my_state['cylc_version'] != CYLC_VERSION:
                gobject.idle_add(self.warn, (
                    "Warning: cylc version mismatch!\n\n"
                    "Suite running with %r.\ngcylc at %r.\n"
                ) % (my_state['cylc_version'], CYLC_VERSION))
            self.stop_summary = None
            self.err_log_lines[:] = []

        is_updated = False
        if 'err_content' in my_state and 'err_size' in my_state:
            self._update_err_log(my_state)
            is_updated = True
        if 'ancestors' in my_state:
            self.ancestors = my_state['ancestors']
            is_updated = True
        if 'ancestors_pruned' in my_state:
            self.ancestors_pruned = my_state['ancestors_pruned']
            is_updated = True
        if 'descendants' in my_state:
            self.descendants = my_state['descendants']
            self.all_families = list(self.descendants)
            is_updated = True
        if 'summary' in my_state and my_state['summary'][0]:
            self._update_state_summary(my_state)
            is_updated = True
        if self.status in [SUITE_STATUS_INITIALISING, SUITE_STATUS_STOPPING]:
            gobject.idle_add(self.info_bar.prog_bar_start, self.status)
        elif self.is_reloading:
            gobject.idle_add(self.info_bar.prog_bar_start, "reloading")
        else:
            gobject.idle_add(self.info_bar.prog_bar_stop)
        # Adjust next update duration:
        # If there is an update, readjust to 1.0s or the mean duration of the
        # last 10 main loop. If there is no update, it should be less frequent
        # than the last update duration.  The maximum duration is
        # max_update_interval seconds.  This should allow the GUI to update
        # more while the main loop is turning around events quickly, but less
        # frequently during quiet time or when the main loop is busy.
        if is_updated:
            self.update_interval = 1.0
            self.last_update_time = time()
        elif time() - self.last_update_time > self.update_interval:
            self.update_interval += 1.0
        if ('mean_main_loop_interval' in my_state and
                my_state['mean_main_loop_interval'] > self.update_interval):
            self.update_interval = my_state['mean_main_loop_interval']
        if self.update_interval > self.max_update_interval:
            self.update_interval = self.max_update_interval

    def _update_err_log(self, my_state):
        """Display suite err log info if necessary."""
        self.err_log_lines += my_state['err_content'].splitlines()
        self.err_log_lines = self.err_log_lines[-10:]
        gobject.idle_add(
            self.info_bar.set_log, "\n".join(self.err_log_lines),
            my_state['err_size'])

    def _update_state_summary(self, my_state):
        """Display suite summary."""
        glbl, states, fam_states = my_state['summary']
        self.mode = glbl['run_mode']

        if self.cfg.use_defn_order:
            nsdo = glbl['namespace definition order']
            if self.ns_defn_order != nsdo:
                self.ns_defn_order = nsdo
                self.dict_ns_defn_order = dict(zip(nsdo, range(0, len(nsdo))))

        self.update_time_str = time2str(glbl['last_updated'])
        self.global_summary = glbl

        if self.restricted_display:
            states = self.filter_for_restricted_display(states)

        self.full_state_summary = states
        self.full_fam_state_summary = fam_states
        self.refilter()

        self.status = glbl['status_string']
        self.is_reloading = glbl['reloading']
        gobject.idle_add(
            self.info_bar.set_state, self.global_summary.get("states", []))
        gobject.idle_add(self.info_bar.set_mode, self.mode)
        gobject.idle_add(self.info_bar.set_update_time, self.update_time_str)
        gobject.idle_add(self.info_bar.set_status, self.status)
コード例 #10
0
ファイル: updater.py プロジェクト: ivorblockley/cylc
    def update(self):
        """Call suite for an update."""
        if self.client is None:
            self.client = SuiteRuntimeServiceClient(
                self.cfg.suite, self.cfg.owner, self.cfg.host, self.cfg.port,
                self.cfg.comms_timeout, self.cfg.my_uuid)
        try:
            my_state = self.client.get_latest_state(full_mode=self.full_mode)
        except ClientError:
            # Bad credential, suite not running, starting up or just stopped?
            if cylc.flags.debug:
                try:
                    traceback.print_exc()
                except IOError:
                    pass  # Cannot print to terminal (session may be closed).
            self.set_stopped()
            return
        # OK
        if cylc.flags.debug:
            sys.stderr.write("%s CONNECTED - suite cylc version=%s\n" % (
                get_current_time_string(), my_state['cylc_version']))
        self.info_bar.set_update_time(None, None)
        if my_state['full_mode']:
            gobject.idle_add(
                self.app_window.set_title, "%s - %s:%s" % (
                    self.cfg.suite, self.client.host, self.client.port))
            # Connected.
            self.full_mode = False
            self.connected = True
            # This status will be very transient:
            self.set_status(SUITE_STATUS_CONNECTED)

            if my_state['cylc_version'] != CYLC_VERSION:
                gobject.idle_add(self.warn, (
                    "Warning: cylc version mismatch!\n\n"
                    "Suite running with %r.\ngcylc at %r.\n"
                ) % (my_state['cylc_version'], CYLC_VERSION))
            self.stop_summary = None
            self.err_log_lines[:] = []

        is_updated = False
        if 'err_content' in my_state and 'err_size' in my_state:
            self._update_err_log(my_state)
            is_updated = True
        if 'ancestors' in my_state:
            self.ancestors = my_state['ancestors']
            is_updated = True
        if 'ancestors_pruned' in my_state:
            self.ancestors_pruned = my_state['ancestors_pruned']
            is_updated = True
        if 'descendants' in my_state:
            self.descendants = my_state['descendants']
            self.all_families = list(self.descendants)
            is_updated = True
        if 'summary' in my_state and my_state['summary'][0]:
            self._update_state_summary(my_state)
            is_updated = True
        if self.status in [SUITE_STATUS_INITIALISING, SUITE_STATUS_STOPPING]:
            gobject.idle_add(self.info_bar.prog_bar_start, self.status)
        elif self.is_reloading:
            gobject.idle_add(self.info_bar.prog_bar_start, "reloading")
        else:
            gobject.idle_add(self.info_bar.prog_bar_stop)
        # Adjust next update duration:
        # If there is an update, readjust to 1.0s or the mean duration of the
        # last 10 main loop. If there is no update, it should be less frequent
        # than the last update duration.  The maximum duration is
        # max_update_interval seconds.  This should allow the GUI to update
        # more while the main loop is turning around events quickly, but less
        # frequently during quiet time or when the main loop is busy.
        if is_updated:
            self.update_interval = 1.0
            self.last_update_time = time()
        elif time() - self.last_update_time > self.update_interval:
            self.update_interval += 1.0
        if ('mean_main_loop_interval' in my_state and
                my_state['mean_main_loop_interval'] > self.update_interval):
            self.update_interval = my_state['mean_main_loop_interval']
        if self.update_interval > self.max_update_interval:
            self.update_interval = self.max_update_interval