Пример #1
0
def list_storage_classes(request):
    """
    Tags: volumes
    ---
    List the volumes of a cloud.

    READ permission required on cloud.
    READ permission required on location.
    ---
    cloud:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict.get('cloud')

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner,
                                  id=cloud_id,
                                  deleted=None)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    if cloud.as_dict()['provider'] != 'kubevirt':
        raise BadRequestError('Only available for KubeVirt clouds')
    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)
    storage_classes = cloud.ctl.storage.list_storage_classes()

    return storage_classes
Пример #2
0
def list_vnfs(request):
    """
    Tags: networks
    ---
    List the virtual network functions of a cloud (KVM only)

    READ permission required on cloud
    ---
    cloud:
      in: path
      required: true
      type: string
    """
    cloud_id = request.matchdict['cloud']

    auth_context = auth_context_from_request(request)

    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()

    try:
        return cloud.ctl.network.list_vnfs()
    except (AttributeError, NotImplementedError):
        raise MistNotImplementedError
Пример #3
0
def delete_dns_zone(request):
    """
    Tags: dns
    ---
    Deletes a specific DNS zone under a cloud.
    REMOVE permission required on zone.
    ---
    cloud:
      in: path
      required: true
      type: string
    zone:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict['cloud']
    zone_id = request.matchdict['zone']

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError()
    try:
        zone = Zone.objects.get(owner=auth_context.owner, id=zone_id,
                                cloud=cloud)
    except Zone.DoesNotExist:
        raise NotFoundError('Zone does not exist')

    auth_context.check_perm("zone", "remove", zone_id)

    zone.ctl.delete_zone()

    return OK
Пример #4
0
def list_networks(owner, cloud_id):
    """List the networks of the specified cloud"""
    ret = {'public': [], 'private': [], 'routers': []}  # FIXME

    try:
        cloud = Cloud.objects.get(owner=owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()

    if not hasattr(cloud.ctl, 'network'):
        return ret

    networks = cloud.ctl.network.list_networks()

    for network in networks:

        network_dict = network.as_dict()
        if hasattr(network, 'location'):
            network_dict['location'] = network.location
        network_dict['subnets'] = [
            subnet.as_dict() for subnet in network.ctl.list_subnets()
        ]

        # TODO: Backwards-compatible network privacy detection, to be replaced
        if not network_dict.get('router_external'):
            ret['private'].append(network_dict)
        else:
            ret['public'].append(network_dict)
    return ret
Пример #5
0
def list_images(owner, cloud_id, term=None):
    """List the images of the specified cloud"""
    try:
        cloud = Cloud.objects.get(owner=owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()

    images = cloud.ctl.compute.list_images(search=term)
    return [image.as_dict() for image in images]
Пример #6
0
def create_dns_record(request):
    """
    Tags: dns
    ---
    Creates a new record under a specific zone.
    CREATE_RESOURCES permission required on cloud.
    CREATE_RECORDS permission required on zone
    ---
    cloud:
      in: path
      required: true
      type: string
    zone:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)

    cloud_id = request.matchdict['cloud']
    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError()

    zone_id = request.matchdict['zone']
    try:
        zone = Zone.objects.get(owner=auth_context.owner,
                                id=zone_id,
                                cloud=cloud)
    except Zone.DoesNotExist:
        raise NotFoundError('Zone does not exist')

    auth_context.check_perm("cloud", "read", cloud_id)
    auth_context.check_perm("zone", "read", zone_id)
    auth_context.check_perm("zone", "create_records", zone_id)
    tags = auth_context.check_perm("record", "add", None)

    params = params_from_request(request)
    dns_cls = RECORDS[params['type']]

    rec = dns_cls.add(owner=auth_context.owner, zone=zone, **params)
    rec.assign_to(auth_context.user)

    if tags:
        resolve_id_and_set_tags(auth_context.owner,
                                'record',
                                rec.id,
                                tags,
                                cloud_id=cloud_id,
                                zone_id=zone_id)

    trigger_session_update(auth_context.owner, ['zones'])
    return rec.as_dict()
Пример #7
0
def list_locations(owner, cloud_id, cached=False):
    """List the locations of the specified cloud"""
    try:
        cloud = Cloud.objects.get(owner=owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    if cached:
        locations = cloud.ctl.compute.list_cached_locations()
    else:
        locations = cloud.ctl.compute.list_locations()
    return [location.as_dict() for location in locations]
Пример #8
0
def delete_subnet(request):
    """
    Tags: networks
    ---
    Delete a subnet

    READ permission required on cloud
    READ permission required on network
    READ permission required on subnet
    REMOVE permission required on subnet
    ---
    cloud_id:
      in: path
      required: true
      type: string
    network_id:
      in: path
      required: true
      type: string
    subnet_id:
      in: path
      required: true
      type: string
    """
    cloud_id = request.matchdict['cloud']
    subnet_id = request.matchdict['subnet']
    network_id = request.matchdict['network']

    auth_context = auth_context_from_request(request)

    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)
    auth_context.check_perm('network', 'read', network_id)
    auth_context.check_perm('network', 'edit_subnets', network_id)

    try:
        cloud = Cloud.objects.get(id=cloud_id, owner=auth_context.owner)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    try:
        network = Network.objects.get(id=network_id, cloud=cloud)
    except Network.DoesNotExist:
        raise NetworkNotFoundError()
    try:
        subnet = Subnet.objects.get(id=subnet_id, network=network)
        subnet.ctl.delete()
    except Subnet.DoesNotExist:
        raise SubnetNotFoundError()

    # Trigger a UI update.
    trigger_session_update(auth_context.owner, ['clouds'])
    return OK
Пример #9
0
def create_subnet(request):
    """
    Tags: networks
    ---
    Create subnet in a given network on a cloud

    ADD permission required on subnet
    READ permission required on cloud
    READ permission required on network
    CREATE_SUBNETS permission required on network
    CREATE_RESOURCES permission required on cloud
    ---
    cloud_id:
      in: path
      required: true
      description: The Cloud ID
      type: string
    network_id:
      in: path
      required: true
      description: The ID of the Network that will contain the new subnet
      type: string
    subnet:
      required: true
      type: object
    """
    cloud_id = request.matchdict['cloud']
    network_id = request.matchdict['network']

    params = params_from_request(request)

    auth_context = auth_context_from_request(request)

    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)
    auth_context.check_perm('cloud', 'create_resources', cloud_id)
    auth_context.check_perm('network', 'read', network_id)
    auth_context.check_perm('network', 'edit_subnets', network_id)

    try:
        cloud = Cloud.objects.get(id=cloud_id, owner=auth_context.owner)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    try:
        network = Network.objects.get(id=network_id, cloud=cloud)
    except Network.DoesNotExist:
        raise NetworkNotFoundError()

    # Create subnet.
    subnet = SUBNETS[cloud.ctl.provider].add(network=network, **params)

    return subnet.as_dict()
Пример #10
0
def list_volumes(owner, cloud_id, cached=False):
    """List the volumes of the specified cloud"""
    try:
        cloud = Cloud.objects.get(owner=owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    if not hasattr(cloud.ctl, 'storage'):
        return []
    if cached:
        volumes = cloud.ctl.storage.list_cached_volumes()
    else:
        volumes = cloud.ctl.storage.list_volumes()
    return [v.as_dict() for v in volumes]
Пример #11
0
def delete_network(request):
    """
    Tags: networks
    ---
    Delete a network and all corresponding subnets

    READ permission required on cloud
    READ permission required on network
    REMOVE permission required on network
    ---
    parameters:
    - name: cloud_id
      in: path
      required: true
      schema:
        type: string
    - name: network_id
      in: path
      required: true
      schema:
        type: string
    """
    cloud_id = request.matchdict['cloud']
    network_id = request.matchdict['network']

    auth_context = auth_context_from_request(request)

    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)
    auth_context.check_perm('network', 'read', network_id)
    auth_context.check_perm('network', 'remove', network_id)

    try:
        cloud = Cloud.objects.get(id=cloud_id, owner=auth_context.owner)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    try:
        network = Network.objects.get(id=network_id, cloud=cloud)
    except me.DoesNotExist:
        raise NetworkNotFoundError()

    # Delete the network
    network.ctl.delete()

    # Schedule a UI update
    trigger_session_update(auth_context.owner, ['clouds'])

    return OK
Пример #12
0
def list_networks(owner, cloud_id, cached=False):
    """List the networks of the specified cloud"""
    try:
        cloud = Cloud.objects.get(owner=owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()

    if not hasattr(cloud.ctl, 'network'):
        return []

    if cached:
        networks = cloud.ctl.network.list_cached_networks()
    else:
        networks = cloud.ctl.network.list_networks()

    return [n.as_dict() for n in networks]
Пример #13
0
def list_zones(owner, cloud_id, cached=False):
    """List the zones of the specified cloud"""
    try:
        cloud = Cloud.objects.get(owner=owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()

    if not hasattr(cloud.ctl, 'dns') or not cloud.dns_enabled:
        return []

    if cached:
        zones = cloud.ctl.dns.list_cached_zones()
    else:
        zones = cloud.ctl.dns.list_zones()

    return [z.as_dict() for z in zones]
Пример #14
0
def star_image(owner, cloud_id, image_id):
    """Toggle image star (star/unstar)"""
    try:
        Cloud.objects.get(owner=owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    from mist.api.images.models import CloudImage
    try:
        image = CloudImage.objects.get(cloud=cloud_id, id=image_id)
    except CloudImage.DoesNotExist:
        raise NotFoundError('CloudImage does not exist')

    image.starred = False if image.starred else True
    image.save()
    trigger_session_update(owner, ['images'])

    return image.as_dict()
Пример #15
0
def list_networks(request):
    """
    Tags: networks
    ---
    List the networks of a cloud

    READ permission required on cloud, networks, and subnets
    ---
    parameters:
    - name: cloud
      in: path
      required: true
      schema:
        type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict.get('cloud')
    params = params_from_request(request)

    if cloud_id:
        cached = bool(params.get('cached', False))
        try:
            Cloud.objects.get(owner=auth_context.owner,
                              id=cloud_id,
                              deleted=None)
        except Cloud.DoesNotExist:
            raise CloudNotFoundError()
        # SEC
        auth_context.check_perm('cloud', 'read', cloud_id)
        networks = filter_list_networks(auth_context, cloud_id, cached=cached)

    else:
        cached = bool(params.get('cached', True))  # return cached by default
        auth_context.check_perm("cloud", "read", None)
        clouds = filter_list_clouds(auth_context)
        networks = []
        for cloud in clouds:
            if cloud.get('enabled'):
                try:
                    networks += filter_list_networks(auth_context,
                                                     cloud.get('id'),
                                                     cached=cached)
                except (CloudUnavailableError, CloudUnauthorizedError):
                    pass

    return networks
Пример #16
0
def delete_dns_record(request):
    """
    Tags: dns
    ---
    Deletes a specific DNS record under a zone.
    REMOVE permission required on zone.
    ---
    cloud:
      in: path
      required: true
      type: string
    zone:
      in: path
      required: true
      type: string
    record:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict['cloud']
    zone_id = request.matchdict['zone']
    record_id = request.matchdict['record']
    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError()
    try:
        zone = Zone.objects.get(owner=auth_context.owner,
                                id=zone_id,
                                cloud=cloud)
    except Zone.DoesNotExist:
        raise NotFoundError('Zone does not exist')
    try:
        record = Record.objects.get(zone=zone, id=record_id)
    except Record.DoesNotExist:
        raise NotFoundError('Record does not exist')

    auth_context.check_perm("record", "remove", record_id)

    record.ctl.delete_record()

    trigger_session_update(auth_context.owner, ['zones'])
    return OK
Пример #17
0
def list_volumes(request):
    """
    Tags: volumes
    ---
    List the volumes of a cloud.

    READ permission required on cloud.
    READ permission required on location.
    ---
    cloud:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)

    params = params_from_request(request)

    cloud_id = request.matchdict.get('cloud')

    if cloud_id:
        cached = bool(params.get('cached', False))
        try:
            Cloud.objects.get(owner=auth_context.owner,
                              id=cloud_id,
                              deleted=None)
        except Cloud.DoesNotExist:
            raise CloudNotFoundError()
        # SEC
        auth_context.check_perm('cloud', 'read', cloud_id)
        volumes = filter_list_volumes(auth_context, cloud_id, cached=cached)
    else:
        auth_context.check_perm("cloud", "read", None)
        clouds = filter_list_clouds(auth_context)
        volumes = []
        for cloud in clouds:
            if cloud.get('enabled'):
                try:
                    vols = filter_list_volumes(auth_context, cloud.get('id'))
                    volumes += vols
                except (CloudUnavailableError, CloudUnauthorizedError):
                    pass

    return volumes
Пример #18
0
def list_subnets(request):
    """
    Tags: networks
    ---
    List the subnets of a network

    READ permission required on cloud
    READ permission required on network
    READ permission required on subnets
    ---
    cloud:
      in: path
      required: true
      type: string
    network_id:
      in: path
      required: true
      description: The DB ID of the network whose subnets will be returned
      type: string
    """
    cloud_id = request.matchdict['cloud']
    network_id = request.matchdict['network']

    auth_context = auth_context_from_request(request)

    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)
    auth_context.check_perm('network', 'read', network_id)

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except Cloud.DoesNotExist:
        raise CloudNotFoundError()
    try:
        network = Network.objects.get(cloud=cloud, id=network_id)
    except Network.DoesNotExist:
        raise NetworkNotFoundError()

    return [subnet.as_dict() for subnet in network.ctl.list_subnets()]
Пример #19
0
def create_volume(request):
    """
    Tags: volumes
    ---
    Create a new volume.

    READ permission required on cloud.
    CREATE_RESOURCES permission required on cloud.
    READ permission required on location.
    CREATE_RESOURCES permission required on location.
    ADD permission required on volumes
    ---
    cloud:
      in: path
      required: true
      type: string
    size:
      required: true
      type: integer
      description: Size of disk in Gb
    name:
      required: true
      type: string
      description: Name of the disk
    location:
      required: true
      type: string
    ex_disk_type:
      type: string
      description: GCE-specific. One of 'pd-standard'(default) or 'pd-ssd'
    ex_volume_type:
      type: string
      description: EC2-specific. One of 'standard', 'io1', 'gp2', 'sc1', 'st1'
    ex_iops:
      type: string
      description: EC2-specific. Needs to be specified if volume_type='io1'
    """
    cloud_id = request.matchdict['cloud']
    params = params_from_request(request)
    name = params.get('name')
    size = params.get('size')
    location = params.get('location')

    auth_context = auth_context_from_request(request)
    owner = auth_context.owner

    if not size:
        raise RequiredParameterMissingError('size')

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner,
                                  id=cloud_id,
                                  deleted=None)
    except me.DoesNotExist:
        raise CloudNotFoundError()

    auth_context.check_perm("cloud", "read", cloud_id)
    auth_context.check_perm("cloud", "create_resources", cloud_id)
    auth_context.check_perm("location", "read", location)
    auth_context.check_perm("location", "create_resources", location)
    tags, _ = auth_context.check_perm("volume", "add", None)

    if not name and cloud.ctl.provider != 'equinixmetal':
        raise RequiredParameterMissingError('name')

    if not hasattr(cloud.ctl, 'storage'):
        raise NotImplementedError()

    volume = cloud.ctl.storage.create_volume(**params)
    # ensure logging_view_decorator will log the right volume id
    request.matchdict['volume'] = volume.id

    if tags:
        add_tags_to_resource(auth_context.owner, volume, tags)

    # Set ownership.
    volume.assign_to(auth_context.user)

    trigger_session_update(owner.id, ['volumes'])

    # SEC
    # Update the RBAC & User/Ownership mappings with the new volume and finally
    # trigger a session update by registering it as a chained task.
    if config.HAS_RBAC:
        owner.mapper.update(volume,
                            callback=async_session_update,
                            args=(
                                owner.id,
                                ['volumes'],
                            ))

    return volume.as_dict()
Пример #20
0
def volume_action(request):
    """
    Tags: volumes
    ---
    Attach or detach a volume to/from a machine.

    READ permission required on cloud.
    READ permission required on volume.
    ATTACH or DETACH permission required on volume.
    ---
    cloud:
      in: path
      required: true
      type: string
    volume:
      in: path
      required: true
      type: string
    machine:
      in: query
      required: true
      type: string
    device:
      in: query
      type: string
      description: eg /dev/sdh. Required for EC2, optional for OpenStack
    """

    auth_context = auth_context_from_request(request)

    params = params_from_request(request)
    action = params.pop('action', '')
    machine_uuid = params.pop('machine', '')

    if action not in ('attach', 'detach'):
        raise BadRequestError()

    if not machine_uuid:
        raise RequiredParameterMissingError('machine')

    cloud_id = request.matchdict.get('cloud')
    external_id = request.matchdict.get('volume_ext')
    if external_id:
        external_id = '/'.join(external_id)

    volume_id = request.matchdict.get('volume_id')

    if cloud_id:

        try:
            cloud = Cloud.objects.get(id=cloud_id,
                                      owner=auth_context.owner,
                                      deleted=None)
        except Cloud.DoesNotExist:
            raise CloudNotFoundError()

        if cloud.ctl.provider in ['azure_arm']:
            external_id = '/' + external_id

        try:
            volume = Volume.objects.get(external_id=external_id,
                                        cloud=cloud,
                                        missing_since=None)
            # ensure logging_view_decorator will log the right thing
            request.matchdict['volume'] = volume.id
        except me.DoesNotExist:
            raise VolumeNotFoundError()

    else:

        try:
            volume = Volume.objects.get(id=volume_id, missing_since=None)
        except me.DoesNotExist:
            raise VolumeNotFoundError()

        cloud = volume.cloud

    try:
        machine = Machine.objects.get(id=machine_uuid, missing_since=None)
    except Machine.DoesNotExist:
        raise MachineNotFoundError()

    auth_context.check_perm("cloud", "read", cloud.id)
    auth_context.check_perm("volume", "read", volume.id)
    auth_context.check_perm("volume", action, volume.id)

    if not hasattr(cloud.ctl, 'storage'):
        raise NotImplementedError()

    getattr(volume.ctl, action)(machine, **params)

    return OK
Пример #21
0
def delete_volume(request):
    """
    Tags: volumes
    ---
    Delete a volume.

    READ permission required on cloud.
    READ permission required on volume.
    REMOVE permission required on volume.
    ---
    parameters:
    - name: cloud
      in: path
      required: true
      schema:
        type: string
    - name: volume
      in: path
      required: true
      schema:
        type: string
    """
    cloud_id = request.matchdict.get('cloud')
    external_id = request.matchdict.get('volume_ext')
    if external_id:
        external_id = '/'.join(external_id)

    volume_id = request.matchdict.get('volume_id')

    auth_context = auth_context_from_request(request)

    if cloud_id:
        try:
            cloud = Cloud.objects.get(id=cloud_id,
                                      owner=auth_context.owner,
                                      deleted=None)
        except Cloud.DoesNotExist:
            raise CloudNotFoundError()

        if cloud.ctl.provider in ['azure_arm']:
            external_id = '/' + external_id

        try:
            volume = Volume.objects.get(external_id=external_id,
                                        cloud=cloud,
                                        missing_since=None)
            # ensure logging_view_decorator will log the right volume id
            request.matchdict['volume'] = volume.id
        except me.DoesNotExist:
            raise VolumeNotFoundError()
    else:
        try:
            volume = Volume.objects.get(id=volume_id, missing_since=None)
        except me.DoesNotExist:
            raise VolumeNotFoundError()

        cloud = volume.cloud

    # SEC
    auth_context.check_perm('cloud', 'read', cloud.id)
    auth_context.check_perm('volume', 'read', volume.id)
    auth_context.check_perm('volume', 'remove', volume.id)

    volume.ctl.delete()

    return OK
Пример #22
0
def create_network(request):
    """
    Tags: networks
    ---
    Create a new network

    If subnet parameters are specified, they will be used to create a new
    subnet in the newly created network.

    ADD permission required on network
    ADD permission required on subnet
    READ permission required on cloud
    CREATE_RESOURCES permission required on cloud
    ---
    parameters:
    - name: cloud_id
      in: path
      required: true
      description: The Cloud ID
      schema:
        type: string
    requestBody:
      description: Foo
      required: true
      content:
        'application/json':
          schema:
            type: object
            properties:
              network:
                type: object
              subnet:
                type: object
            required:
            - network
    """
    cloud_id = request.matchdict['cloud']

    params = params_from_request(request)
    network_params = params.get('network')
    subnet_params = params.get('subnet')

    auth_context = auth_context_from_request(request)

    if not network_params:
        raise RequiredParameterMissingError('network')

    if subnet_params and not subnet_params.get('cidr'):
        raise RequiredParameterMissingError('cidr')

    auth_context.check_perm("cloud", "read", cloud_id)
    auth_context.check_perm("cloud", "create_resources", cloud_id)
    tags, _ = auth_context.check_perm("network", "add", None)

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id)
    except me.DoesNotExist:
        raise CloudNotFoundError()

    # Is network support available?
    if not hasattr(cloud.ctl, 'network'):
        raise NotImplementedError()

    # Create the new network
    network = NETWORKS[cloud.ctl.provider].add(cloud=cloud, **network_params)
    network.assign_to(auth_context.user)

    if tags:
        add_tags_to_resource(auth_context.owner, network, tags)

    # Bundling Subnet creation in this call because it is required for
    # backwards compatibility with the current UI  # FIXME
    if subnet_params:
        try:
            # Create a DB document for the new subnet and call libcloud to
            # declare it on the cloud provider
            SUBNETS[cloud.ctl.provider].add(network=network, **subnet_params)
        except Exception as exc:
            # Cleaning up the network object in case subnet creation fails
            # for any reason
            network.ctl.delete()
            network.delete()
            raise exc

    return network.as_dict()