Beispiel #1
0
def get_job(job_id):  # noqa: E501
    """Get job

    null # noqa: E501

    :param job_id:
    :type job_id: str

    :rtype: GetJobResponse
    """
    from mist.api.logs.methods import get_story
    from mist.api.exceptions import NotFoundError
    try:
        auth_context = connexion.context['token_info']['auth_context']
    except KeyError:
        return 'Authentication failed', 401
    try:
        story = get_story(auth_context.owner.id, job_id)
    except NotFoundError:
        return 'Job not found', 404
    for key in ("type", "story_id", "key_id"):
        story.pop(key, None)
    if story.get("owner_id"):
        story["org"] = story.pop("owner_id", None)
    if story.get("job"):
        story["action"] = story.pop("job", None)
    for log in story.get("logs"):
        if log.get("owner_id"):
            log["org"] = log.pop("owner_id", None)
    return GetJobResponse(data=story,
                          meta=ResponseMetadata(total=1, returned=1))
Beispiel #2
0
    def get_docker_endpoint(self, owner, cloud_id, job_id=None):
        if job_id:
            event = get_story(owner.id, job_id)
            assert owner.id == event['owner_id'], 'Owner ID mismatch!'
            self.host, docker_port = config.DOCKER_IP, config.DOCKER_PORT
            return docker_port, event['logs'][0]['container_id']

        cloud = Cloud.objects.get(owner=owner, id=cloud_id, deleted=None)
        self.host, docker_port = dnat(owner, self.host, cloud.port)
        return docker_port, cloud
Beispiel #3
0
def show_job(request):
    """Fetch a story.

    ---

    job_id:
      in: path
      type: string
      required: true

    """
    auth_context = auth_context_from_request(request)
    job_id = request.matchdict['job_id']
    return get_story(auth_context.owner.id, job_id)
Beispiel #4
0
def show_job(request):
    """
    Tags: logs+stories
    ---
    Fetches a story.
    ---
    job_id:
      in: path
      type: string
      required: true
    """
    auth_context = auth_context_from_request(request)
    job_id = request.matchdict['job_id']
    if not job_id:
        raise RequiredParameterMissingError('job_id')
    return get_story(auth_context.owner.id, job_id)
Beispiel #5
0
def test_close_story(load_logs):
    """Test closing stories.

    Fetch an open story and close it manually.

    """
    owner_id = get_owner_id(load_logs)

    for story_type in ('incident', ):
        stories = get_stories(story_type,
                              owner_id=owner_id,
                              expand=True,
                              pending=True)
        assert len(stories) is 1

        story = stories[0]
        assert len(story['logs']) is 1
        assert not story['finished_at']
        assert story['type'] == story_type

        for log in story['logs']:
            assert log['type'] in TYPES[story_type]
            assert log['owner_id'] == story['owner_id']
            assert log['%s_id' % story_type] == story['story_id']

        # Close the story.
        log_event(owner_id=owner_id,
                  action='close_story',
                  event_type='request',
                  story_id=story['story_id'])

        # Wait for index refresh.
        time.sleep(1)

        # Ensure there are no more pending stories.
        stories = get_stories(story_type,
                              owner_id=owner_id,
                              expand=True,
                              pending=True)
        assert len(stories) is 0

        # Verify the story's `finished_at` timestamp.
        story = get_story(owner_id=owner_id, story_id=story['story_id'])
        assert story['finished_at']
        assert story['type'] == story_type
        assert len(story['logs']) is 2
Beispiel #6
0
def test_single_story(load_logs):
    """Test fetching a single story.

    Fetch a single story and verify its list of logs.

    """
    owner_id = get_owner_id(load_logs)
    job_id = get_story_id(load_logs)

    story = get_story(owner_id=owner_id, story_id=job_id)
    assert story['finished_at']
    assert len(story['logs']) is 3

    for log in story['logs']:
        assert log['type'] in TYPES['job']
        assert log['owner_id'] == story['owner_id']
        assert log['job_id'] == story['story_id']
        assert log['action'] in ('run_script', 'script_started',
                                 'script_finished')
Beispiel #7
0
def end_job(request):
    """End a running job.

    Close/end an open job. This is very similar to the close_story API
    endpoint. However, this endpoint may be used to perform additional
    actions upon closing an open story.

    ---

    job_id:
      in: path
      type: string
      required: true

    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)

    try:
        from mist.core.orchestration.models import Stack
        from mist.core.orchestration.methods import finish_workflow
    except ImportError:
        raise NotImplementedError()

    job_id = request.matchdict['job_id']
    job = get_story(auth_context.owner.id, job_id)  # Raises NotFoundError.

    stack_id = job['logs'][0].get('stack_id')
    workflow = job['logs'][0].get('workflow', 'install')
    try:
        stack = Stack.objects.get(owner=auth_context.owner,
                                  id=stack_id, deleted=None)
    except Stack.DoesNotExist:
        raise NotFoundError('Stack does not exist')

    # Finish the workflow. Update the Stack and its status.
    finish_workflow(stack, job_id, workflow, params.get('exit_code'),
                    params.get('cmdout'), params.get('error'),
                    params.get('node_instances'), params.get('outputs'))

    # FIXME:The MistClient expects a JSON-decodable response.
    # return Response('OK', 200)
    return {}
Beispiel #8
0
def end_job(request):
    """
    Tags: logs+stories
    ---
    Ends a running job.
    Closes/ends an open job. This is very similar to the close_story API
    endpoint. However, this endpoint may be used to perform additional
    actions upon closing an open story.
    ---
    job_id:
      in: path
      type: string
      required: true
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)

    if config.HAS_ORCHESTRATION:
        from mist.orchestration.models import Stack
        from mist.orchestration.methods import finish_workflow
    else:
        raise NotImplementedError()

    job_id = request.matchdict['job_id']
    job = get_story(auth_context.owner.id, job_id)  # Raises NotFoundError.

    stack_id = job['logs'][0].get('stack_id')
    workflow = job['logs'][0].get('workflow', 'install')
    try:
        stack = Stack.objects.get(owner=auth_context.owner,
                                  id=stack_id,
                                  deleted=None)
    except Stack.DoesNotExist:
        raise NotFoundError('Stack does not exist')

    if params.get('action', '') == 'cloud_init_finished':
        if not params.get('machine_name'):
            raise RequiredParameterMissingError('machine_name')
        try:
            error = bool(int(params.get('error')))
        except (TypeError, ValueError):
            raise RequiredParameterMissingError('error')
        # Log cloud-init's outcome. This is expected by the kubernetes
        # blueprint in order for execution to continue. The cloud-init
        # script POSTs back once it's done, since there is no other way
        # to know when it's finished running, especially in case there
        # is no SSH connectivity to the machine.
        log_event(
            job_id=job_id,
            workflow=workflow,
            stack_id=stack.id,
            owner_id=stack.owner.id,
            template_id=stack.template.id,
            machine_name=params['machine_name'],
            action=params['action'],
            event_type='job',
            error=error,
        )
    else:
        # Finish the workflow. Update the Stack and its status.
        finish_workflow(stack, job_id, workflow, params.get('exit_code'),
                        params.get('cmdout'), params.get('error'),
                        params.get('node_instances'), params.get('outputs'))

        # Delete the Stack, if it's been deleted, rather than just uninstalled.
        action = job['logs'][1].get('action', '')
        if workflow == 'uninstall' and action == 'delete_stack':
            stack.update(set__deleted=datetime.datetime.utcnow())
            trigger_session_update(auth_context.owner, ['stacks'])

    # FIXME:The MistClient expects a JSON-decodable response.
    # return Response('OK', 200)
    return {}