Пример #1
0
def list_datastores(request):
    """
    Tags: datastores
    ---
    Lists datastores on cloud.
    Only supported for Vsphere.
    READ permission required on cloud.
    ---
    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 NotFoundError('Cloud does not exist')

    if cloud.as_dict()['provider'] != 'vsphere':
        raise BadRequestError('Only available for vSphere clouds.')
    # SEC
    auth_context.check_perm('cloud', 'read', cloud_id)
    try:
        datastores = cloud.ctl.compute.list_datastores()
        return datastores
    except Exception as e:
        log.error("Could not list datastores for cloud %s: %r" % (cloud, e))
        raise MistNotImplementedError()
Пример #2
0
def list_projects(request):
    """
    Tags: projects
    ---
    Lists projects on cloud.
    Only supported for EquinixMetal.
    For other providers,returns an empty list
    READ permission required on cloud.
    ---
    cloud:
      in: path
      required: true
      type: string
    """
    auth_context = auth_context_from_request(request)
    cloud_id = request.matchdict['cloud']

    # SEC
    auth_context.check_perm("cloud", "read", cloud_id)
    try:
        cloud = Cloud.objects.get(owner=auth_context.owner,
                                  id=cloud_id,
                                  deleted=None)
    except Cloud.DoesNotExist:
        raise NotFoundError('Cloud does not exist')
    try:
        projects = methods.list_projects(auth_context.owner, cloud_id)
    except Exception as e:
        log.error("Could not list projects for cloud %s: %r" % (cloud, e))
        raise MistNotImplementedError()

    return projects
Пример #3
0
 def _delete_subnet(self, subnet, libcloud_subnet):
     raise MistNotImplementedError()
Пример #4
0
 def _delete_network(self, network, libcloud_network):
     raise MistNotImplementedError()
Пример #5
0
def machine_console(request):
    """
    Tags: machines
    ---
    Open VNC console.
    Generate and return an URI to open a VNC console to target machine
    READ permission required on cloud.
    READ permission required on machine.
    ---
    cloud:
      in: path
      required: true
      type: string
    machine:
      in: path
      required: true
      type: string
    rdp_port:
      default: 3389
      in: query
      required: true
      type: integer
    host:
      in: query
      required: true
      type: string
    """
    cloud_id = request.matchdict.get('cloud')

    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,
                                          state__ne='terminated')
            # 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)

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

    if machine.cloud.ctl.provider not in ['vsphere', 'openstack', 'libvirt']:
        raise MistNotImplementedError(
            "VNC console only supported for vSphere, OpenStack or KVM")

    if machine.cloud.ctl.provider == 'libvirt':
        import xml.etree.ElementTree as ET
        from html import unescape
        from datetime import datetime
        import hmac
        import hashlib
        xml_desc = unescape(machine.extra.get('xml_description', ''))
        root = ET.fromstring(xml_desc)
        vnc_element = root.find('devices').find('graphics[@type="vnc"]')
        if not vnc_element:
            raise MethodNotAllowedError(
                "VNC console not supported by this KVM domain")
        vnc_port = vnc_element.attrib.get('port')
        vnc_host = vnc_element.attrib.get('listen')
        from mongoengine import Q
        # Get key associations, prefer root or sudoer ones
        key_associations = KeyMachineAssociation.objects(
            Q(machine=machine.parent) & (Q(ssh_user='******') | Q(sudo=True))) \
            or KeyMachineAssociation.objects(machine=machine.parent)
        if not key_associations:
            raise ForbiddenError()
        key_id = key_associations[0].key.id
        host = '%s@%s:%d' % (key_associations[0].ssh_user,
                             machine.parent.hostname, key_associations[0].port)
        expiry = int(datetime.now().timestamp()) + 100
        msg = '%s,%s,%s,%s,%s' % (host, key_id, vnc_host, vnc_port, expiry)
        mac = hmac.new(config.SECRET.encode(),
                       msg=msg.encode(),
                       digestmod=hashlib.sha256).hexdigest()
        base_ws_uri = config.CORE_URI.replace('http', 'ws')
        proxy_uri = '%s/proxy/%s/%s/%s/%s/%s/%s' % (
            base_ws_uri, host, key_id, vnc_host, vnc_port, expiry, mac)
        return render_to_response('../templates/novnc.pt', {'url': proxy_uri})
    if machine.cloud.ctl.provider == 'vsphere':
        console_uri = machine.cloud.ctl.compute.connection.ex_open_console(
            machine.machine_id)
        protocol, host = config.CORE_URI.split('://')
        protocol = protocol.replace('http', 'ws')
        params = urllib.parse.urlencode({'url': console_uri})
        proxy_uri = f"{protocol}://{host}/wsproxy/?{params}"
        return render_to_response('../templates/novnc.pt', {'url': proxy_uri})
    else:
        console_url = machine.cloud.ctl.compute.connection.ex_open_console(
            machine.machine_id)
    raise RedirectError(console_url)
Пример #6
0
def add_machine(request):
    """
    Tags: machines
    ---
    Add a machine to an OtherServer/Libvirt Cloud.
    READ permission required on cloud.
    EDIT permission required on cloud.
    READ permission required on key.
    ---
    cloud:
      in: path
      required: true
      type: string
    machine_hostname:
      type: string
      required: true
    operating_system:
      type: string
    machine_name:
      type: string
    machine_key:
      type: string
    machine_user:
      type: string
    machine_port:
      type: string
    remote_desktop_port:
      type: string
    monitoring:
      type: boolean
    images_location:
      type: string
    """
    cloud_id = request.matchdict.get('cloud')

    auth_context = auth_context_from_request(request)

    try:
        cloud = Cloud.objects.get(owner=auth_context.owner,
                                  id=cloud_id,
                                  deleted=None)
    except Cloud.DoesNotExist:
        raise NotFoundError('Cloud does not exist')

    if cloud.ctl.provider not in ['libvirt', 'bare_metal']:
        raise MistNotImplementedError()

    params = params_from_request(request)
    machine_hostname = params.get('machine_hostname')
    if not machine_hostname:
        raise RequiredParameterMissingError("machine_hostname")

    operating_system = params.get('operating_system', '')
    machine_name = params.get('machine_name', '')
    machine_key = params.get('machine_key', '')
    machine_user = params.get('machine_user', '')
    machine_port = params.get('machine_port', 22)
    remote_desktop_port = params.get('remote_desktop_port', '')
    images_location = params.get('images_location', '')
    monitoring = params.get('monitoring', False)

    job_id = params.get('job_id')
    if not job_id:
        job = 'add_machine'
        job_id = uuid.uuid4().hex
    else:
        job = None

    auth_context.check_perm("cloud", "read", cloud_id)
    auth_context.check_perm("cloud", "edit", cloud_id)

    if machine_key:
        auth_context.check_perm("key", "read", machine_key)

    log.info('Adding host machine %s on cloud %s' % (machine_name, cloud_id))

    try:
        machine = cloud.ctl.add_machine(host=machine_hostname,
                                        ssh_user=machine_user,
                                        ssh_port=machine_port,
                                        ssh_key=machine_key,
                                        name=machine_name,
                                        os_type=operating_system,
                                        rdp_port=remote_desktop_port,
                                        images_location=images_location)
    except Exception as e:
        raise MachineCreationError("Adding host got exception %r" % e, exc=e)

    # Enable monitoring
    if monitoring:
        monitor = enable_monitoring(
            auth_context.owner,
            cloud.id,
            machine.machine_id,
            no_ssh=not (machine.os_type == 'unix'
                        and KeyMachineAssociation.objects(machine=machine)))

    ret = {
        'id': machine.id,
        'name': machine.name,
        'extra': {},
        'public_ips': machine.public_ips,
        'private_ips': machine.private_ips,
        'job_id': job_id,
        'job': job
    }

    if monitoring:
        ret.update({'monitoring': monitor})

    return ret