示例#1
0
 def __monitor_vm_events(self):
     session = self.get_session()
     vmuuid = self.get_uuid()
     ssh_client = ssh_helper.prepare_ssh_client(session, vmuuid)
     try:
         cmd = docker.prepare_request_cmd()
         log.info("__monitor_vm_events is running '%s' on VM '%s'"
                  % (cmd, vmuuid))
         stdin, stdout, _ = ssh_client.exec_command(cmd)
         stdin.write(docker.prepare_request_stdin('GET', '/events'))
         self._ssh_client = ssh_client
         # Not that we are listening for events, get the latest state
         docker.update_docker_ps(self)
         # set unblocking io for select.select
         stdout_fd = stdout.channel.fileno()
         fcntl.fcntl(stdout_fd,
                     fcntl.F_SETFL,
                     os.O_NONBLOCK | fcntl.fcntl(stdout_fd, fcntl.F_GETFL))
         # @todo: should make this more sane
         skippedheader = False
         openbrackets = 0
         data = ""
         while not self._stop_monitoring_request:
             rlist, _, _ = select.select([stdout_fd], [], [],
                                         MONITOR_EVENTS_POLL_INTERVAL)
             if not rlist:
                 continue
             try:
                 # @todo: should read more than one char at once
                 lastread = stdout.read(1)
             except IOError, exception:
                 if exception[0] not in (errno.EAGAIN, errno.EINTR):
                     raise
                 sys.exc_clear()
                 continue
             if lastread == '':
                 break
             data = data + lastread
             if (not skippedheader and lastread == "\n"
                     and len(data) >= 4 and data[-4:] == "\r\n\r\n"):
                 data = ""
                 skippedheader = True
             elif lastread == '{':
                 openbrackets = openbrackets + 1
             elif lastread == '}':
                 openbrackets = openbrackets - 1
                 if openbrackets == 0:
                     event = simplejson.loads(data)
                     self.handle_docker_event(event)
                     data = ""
             if len(data) >= 2048:
                 raise util.XSContainerException('__monitor_vm_events' +
                                                 'is full')
     finally:
         try:
             ssh_client.close()
         except Exception:
             util.log.exception("Error when closing ssh_client for %r"
                                % ssh_client)
     log.info('__monitor_vm_events (%s) exited' % cmd)
示例#2
0
def execute_docker_event_listen(session, vmuuid, stoprequest):
    skippedheader = False
    data = ""
    openbrackets = 0
    request = "GET /events HTTP/1.0\r\n\r\n"
    connector = _get_connector(session, vmuuid)
    for read_data in connector.execute_docker_data_listen(session,
                                                          vmuuid,
                                                          request,
                                                          stoprequest):
        for character in read_data:
            data = data + character
            if (not skippedheader and character == "\n" and
                    len(data) >= 4 and data[-4:] == "\r\n\r\n"):
                data = ""
                skippedheader = True
            elif character == '{':
                openbrackets = openbrackets + 1
            elif character == '}':
                openbrackets = openbrackets - 1
                if openbrackets == 0:
                    event = util.convert_dict_to_ascii(json.loads(data))
                    yield event
                    data = ""
            if len(read_data) >= 2048:
                raise util.XSContainerException('execute_docker_event_listen' +
                                                'is full')
示例#3
0
def get_top_dict(session, vmuuid, container):
    _verify_or_throw_container(container)
    result = _get_api_json(session, vmuuid, '/containers/%s/top' % (container))
    titles = result['Titles']
    psentries = []
    for process in result['Processes']:
        process_dict = {}
        item = 0
        if len(titles) > len(process):
            raise util.XSContainerException("Can't parse top output")
        for title in titles:
            process_dict.update({title: process[item]})
            item = item + 1
        psentries.append({'Process': process_dict})
    return psentries
示例#4
0
def find_latest_tools_iso_path():
    tools_iso_paths = glob.glob(XS_TOOLS_ISO_PATH)
    if len(tools_iso_paths) == 0:
        raise util.XSContainerException("Can't locate XS tools in %s." %
                                        (XS_TOOLS_ISO_PATH))
    elif len(tools_iso_paths) == 1:
        return tools_iso_paths[0]
    else:
        # Let's first loose the xs-tools.iso without a release
        tools_iso_path_wo_releaseless = []
        for path in tools_iso_paths:
            basename = os.path.basename(path)
            if basename.count("-") != 2:
                tools_iso_path_wo_releaseless.append(path)
        # Then sort the remaining
        tools_iso_path_wo_releaseless.sort(
            key=lambda s: map(str, re.split('[.-]', s)))
        # And return the last number out of the sorted list
        return tools_iso_path_wo_releaseless[-1]
示例#5
0
def get_suitable_vm_ip(session, vmuuid):
    ips = get_vm_ips(session, vmuuid)
    stage1filteredips = []
    for address in ips.itervalues():
        if ':' not in address:
            # If we get here - it's ipv4
            if address.startswith('169.254.'):
                # we prefer host internal networks and put them at the front
                stage1filteredips.insert(0, address)
            else:
                stage1filteredips.append(address)
        else:
            # Ignore ipv6 as Dom0 won't be able to use it
            pass
    for address in stage1filteredips:
        if util.test_connection(address, 22):
            return address
    raise util.XSContainerException(
        "No valid IP found for vmuuid %s" % (vmuuid))
示例#6
0
def _interact_with_api(session,
                       vmuuid,
                       request_type,
                       request,
                       message_error=False):
    provided_stdin = prepare_request_stdin(request_type, request)
    stdout = ssh_helper.execute_ssh(session,
                                    vmuuid,
                                    prepare_request_cmd(),
                                    stdin_input=provided_stdin)
    headerend = stdout.index('\r\n\r\n')
    header = stdout[:headerend]
    body = stdout[headerend + 4:]
    # ToDo: Should use re
    headersplits = header.split('\r\n', 2)[0].split(' ')
    # protocol = headersplits[0]
    statuscode = headersplits[1]
    if statuscode[0] != '2':
        # this did not work
        status = ' '.join(headersplits[2:])
        failure_title = "Container Management Error"
        failure_body = body.strip()
        if failure_body == "":
            if statuscode == "304":
                # 304 does not have a body and is quite common.
                failure_body = ("The requested operation is currently not "
                                "possible. Please try again later.")
            else:
                failure_body = ("The requested operation failed.")
        failure_body = failure_body + " (" + statuscode + ")"
        if ":" in failure_body:
            (failure_title, failure_body) = failure_body.split(":", 1)
        if message_error:
            api_helper.send_message(session, vmuuid, failure_title,
                                    failure_body)
        message = ("Request '%s' led to status %s - %s: %s" %
                   (request, status, failure_title, failure_body))
        log.info(message)
        raise util.XSContainerException(message)
    return body
示例#7
0
def _verify_or_throw_container(container):
    if not re.match('^[a-z0-9_.-]+$', container):
        raise util.XSContainerException("Invalid container")