Example #1
0
def create_snapshot(machine, name):  # noqa: E501
    """Create snapshot

    Create snapshots of target machine # noqa: E501

    :param machine:
    :type machine: str
    :param name:
    :type name: str

    :rtype: object
    """
    from mist.api.methods import list_resources
    try:
        auth_context = connexion.context['token_info']['auth_context']
    except KeyError:
        return 'Authentication failed', 401
    try:
        [machine], total = list_resources(auth_context,
                                          'machine',
                                          search=machine,
                                          limit=1)
    except ValueError:
        return 'Machine does not exist', 404
    try:
        auth_context.check_perm('machine', 'read', machine.id)
        auth_context.check_perm('machine', 'list_snapshots', machine.id)
        auth_context.check_perm('machine', 'create_snapshots', machine.id)
    except PolicyUnauthorizedError:
        return 'You are not authorized to perform this action', 403
    try:
        result = machine.ctl.create_snapshot(name)
    except ForbiddenError:
        return 'Action not supported on target machine', 422
    except BadRequestError as e:
        return str(e), 400
    methods.run_post_action_hooks(machine, 'create_snapshot',
                                  auth_context.user, result)
    return {'name': name}
Example #2
0
def rename_machine(machine, name):  # noqa: E501
    """Rename machine

    Rename target machine # noqa: E501

    :param machine:
    :type machine: str
    :param name: New machine name
    :type name: str

    :rtype: None
    """
    from mist.api.methods import list_resources
    try:
        auth_context = connexion.context['token_info']['auth_context']
    except KeyError:
        return 'Authentication failed', 401
    from mist.api.logs.methods import log_event
    try:
        [machine], total = list_resources(auth_context, 'machine',
                                          search=machine, limit=1)
    except ValueError:
        return 'Machine does not exist', 404
    if not methods.run_pre_action_hooks(machine, 'rename', auth_context.user):
        return 'OK', 200  # webhook requires stopping action propagation
    log_event(
        auth_context.owner.id, 'request', 'rename_machine',
        machine_id=machine.id, user_id=auth_context.user.id,
    )
    try:
        auth_context.check_perm('machine', 'rename', machine.id)
    except PolicyUnauthorizedError:
        return 'You are not authorized to perform this action', 403
    try:
        result = machine.ctl.rename(name)
    except ForbiddenError:
        return 'Action not supported on target machine', 422
    methods.run_post_action_hooks(machine, 'rename', auth_context.user, result)
    return 'Machine renamed successfully'
Example #3
0
def revert_to_snapshot(machine, snapshot):  # noqa: E501
    """Revert to snapshot

    Revert machine to snapshot # noqa: E501

    :param machine:
    :type machine: str
    :param snapshot:
    :type snapshot: str

    :rtype: None
    """
    from mist.api.methods import list_resources
    try:
        auth_context = connexion.context['token_info']['auth_context']
    except KeyError:
        return 'Authentication failed', 401
    try:
        [machine], total = list_resources(auth_context,
                                          'machine',
                                          search=machine,
                                          limit=1)
    except ValueError:
        return 'Machine does not exist', 404
    try:
        auth_context.check_perm('machine', 'read', machine.id)
        auth_context.check_perm('machine', 'list_snapshots', machine.id)
        auth_context.check_perm('machine', 'revert_to_snapshots', machine.id)
    except PolicyUnauthorizedError:
        return 'You are not authorized to perform this action', 403
    try:
        result = machine.ctl.revert_to_snapshot(snapshot)
    except BadRequestError as e:
        return str(e), 400
    methods.run_post_action_hooks(machine, 'revert_to_snapshot',
                                  auth_context.user, result)
    return 'Revert machine to snapshot issued successfully'
Example #4
0
def machine_actions(request):
    """
    Tags: machines
    ---
    Calls a machine action on cloud that supports it.
    READ permission required on cloud.
    ACTION permission required on machine(ACTION can be START,
    STOP, DESTROY, REBOOT or RESIZE, RENAME for some providers).
    ---
    machine_uuid:
      in: path
      required: true
      type: string
    action:
      enum:
      - start
      - stop
      - reboot
      - destroy
      - resize
      - rename
      - create_snapshot
      - remove_snapshot
      - revert_to_snapshot
      required: true
      type: string
    name:
      description: The new name of the renamed machine
      type: string
    size:
      description: The size id of the plan to resize
      type: string
    snapshot_name:
      description: The name of the snapshot to create/remove/revert_to
    snapshot_description:
      description: The description of the snapshot to create
    snapshot_dump_memory:
      description: Dump the machine's memory in the snapshot
      default: false
    snapshot_quiesce:
      description: Enable guest file system quiescing
      default: false
    """
    cloud_id = request.matchdict.get('cloud')
    params = params_from_request(request)
    action = params.get('action', '')
    name = params.get('name', '')
    size_id = params.get('size', '')
    memory = params.get('memory', '')
    cpus = params.get('cpus', '')
    cpu_shares = params.get('cpu_shares', '')
    cpu_units = params.get('cpu_units', '')
    snapshot_name = params.get('snapshot_name')
    snapshot_description = params.get('snapshot_description')
    snapshot_dump_memory = params.get('snapshot_dump_memory')
    snapshot_quiesce = params.get('snapshot_quiesce')
    auth_context = auth_context_from_request(request)

    if cloud_id:
        machine_id = request.matchdict['machine']
        auth_context.check_perm("cloud", "read", cloud_id)
        try:
            machine = Machine.objects.get(cloud=cloud_id,
                                          machine_id=machine_id,
                                          state__ne='terminated')
            # used by logging_view_decorator
            request.environ['machine_uuid'] = machine.id
        except Machine.DoesNotExist:
            raise NotFoundError("Machine %s doesn't exist" % machine_id)
    else:
        machine_uuid = request.matchdict['machine_uuid']
        try:
            machine = Machine.objects.get(id=machine_uuid)
            # VMs in libvirt can be started no matter if they are terminated
            if machine.state == 'terminated' and not isinstance(
                    machine.cloud, LibvirtCloud):
                raise NotFoundError("Machine %s has been terminated" %
                                    machine_uuid)
            # used by logging_view_decorator
            request.environ['machine_id'] = machine.machine_id
            request.environ['cloud_id'] = machine.cloud.id
        except Machine.DoesNotExist:
            raise NotFoundError("Machine %s doesn't exist" % machine_uuid)

        cloud_id = machine.cloud.id
        auth_context.check_perm("cloud", "read", cloud_id)

    if machine.cloud.owner != auth_context.owner:
        raise NotFoundError("Machine %s doesn't exist" % machine.id)

    auth_context.check_perm("machine", action, machine.id)

    actions = ('start', 'stop', 'reboot', 'destroy', 'resize', 'rename',
               'undefine', 'suspend', 'resume', 'remove', 'list_snapshots',
               'create_snapshot', 'remove_snapshot', 'revert_to_snapshot',
               'clone')

    if action not in actions:
        raise BadRequestError("Action '%s' should be "
                              "one of %s" % (action, actions))

    if not methods.run_pre_action_hooks(machine, action, auth_context.user):
        return OK  # webhook requires stopping action propagation

    if action == 'destroy':
        result = methods.destroy_machine(auth_context.owner, cloud_id,
                                         machine.machine_id)
    elif action == 'remove':
        log.info('Removing machine %s in cloud %s' %
                 (machine.machine_id, cloud_id))

        # if machine has monitoring, disable it
        if machine.monitoring.hasmonitoring:
            try:
                disable_monitoring(auth_context.owner,
                                   cloud_id,
                                   machine_id,
                                   no_ssh=True)
            except Exception as exc:
                log.warning("Didn't manage to disable monitoring, maybe the "
                            "machine never had monitoring enabled. Error: %r" %
                            exc)
        result = machine.ctl.remove()
        # Schedule a UI update
        trigger_session_update(auth_context.owner, ['clouds'])
    elif action in ('start', 'stop', 'reboot', 'clone', 'undefine', 'suspend',
                    'resume'):
        result = getattr(machine.ctl, action)()
    elif action == 'rename':
        if not name:
            raise BadRequestError("You must give a name!")
        result = getattr(machine.ctl, action)(name)
    elif action == 'resize':
        _, constraints = auth_context.check_perm("machine", "resize",
                                                 machine.id)
        # check cost constraint
        cost_constraint = constraints.get('cost', {})
        if cost_constraint:
            try:
                from mist.rbac.methods import check_cost
                check_cost(auth_context.org, cost_constraint)
            except ImportError:
                pass
        kwargs = {}
        if memory:
            kwargs['memory'] = memory
        if cpus:
            kwargs['cpus'] = cpus
        if cpu_shares:
            kwargs['cpu_shares'] = cpu_shares
        if cpu_units:
            kwargs['cpu_units'] = cpu_units
        result = getattr(machine.ctl, action)(size_id, kwargs)
    elif action == 'list_snapshots':
        return machine.ctl.list_snapshots()
    elif action in ('create_snapshot', 'remove_snapshot',
                    'revert_to_snapshot'):
        kwargs = {}
        if snapshot_description:
            kwargs['description'] = snapshot_description
        if snapshot_dump_memory:
            kwargs['dump_memory'] = bool(snapshot_dump_memory)
        if snapshot_quiesce:
            kwargs['quiesce'] = bool(snapshot_quiesce)
        result = getattr(machine.ctl, action)(snapshot_name, **kwargs)

    methods.run_post_action_hooks(machine, action, auth_context.user, result)

    # TODO: We shouldn't return list_machines, just OK. Save the API!
    return methods.filter_list_machines(auth_context, cloud_id)
Example #5
0
def resize_machine(machine, size):  # noqa: E501
    """Resize machine

    Resize target machine # noqa: E501

    :param machine:
    :type machine: str
    :param size:
    :type size: str

    :rtype: None
    """
    from mist.api.methods import list_resources
    try:
        auth_context = connexion.context['token_info']['auth_context']
    except KeyError:
        return 'Authentication failed', 401
    from mist.api.logs.methods import log_event
    try:
        [machine], total = list_resources(auth_context, 'machine',
                                          search=machine, limit=1)
    except ValueError:
        return 'Machine does not exist', 404
    if not methods.run_pre_action_hooks(machine, 'resize', auth_context.user):
        return 'OK', 200  # webhook requires stopping action propagation
    try:
        [size], total = list_resources(auth_context, 'size',
                                       cloud=machine.cloud.id,
                                       search=size, limit=1)
    except ValueError:
        return 'Size does not exist', 404
    try:
        _, constraints = auth_context.check_perm(
            'machine', 'resize', machine.id)
    except PolicyUnauthorizedError:
        return 'You are not authorized to perform this action', 403
    # check cost constraint
    cost_constraint = constraints.get('cost', {})
    if cost_constraint:
        try:
            from mist.rbac.methods import check_cost
            check_cost(auth_context.org, cost_constraint)
        except ImportError:
            pass
    # check size constraint
    size_constraint = constraints.get('size', {})
    if size_constraint:
        try:
            from mist.rbac.methods import check_size
            check_size(machine.cloud.id, size_constraint, size)
        except ImportError:
            pass
    log_event(
        auth_context.owner.id, 'request', 'resize_machine',
        machine_id=machine.id, user_id=auth_context.user.id,
    )
    try:
        result = machine.ctl.resize(size.id, {})
    except ForbiddenError:
        return 'Action not supported on target machine', 422
    except BadRequestError as e:
        return str(e), 400
    methods.run_post_action_hooks(machine, 'resize', auth_context.user, result)
    return 'Machine resize issued successfully'