Beispiel #1
0
def provider_over_allocation_enforcement(identity, user):
    provider = identity.provider
    action = provider.over_allocation_action
    if not action:
            logger.debug("No 'over_allocation_action' provided for %s" % provider)
            return False
    driver = get_cached_driver(identity=identity)
    esh_instances = driver.list_instances()
    #TODO: Parallelize this operation so you don't wait for larger instances to finish 'wait_for' task below..
    for instance in esh_instances:
        try:
            if driver._is_active_instance(instance):
                # Suspend active instances, update the task in the DB
                # NOTE: identity.created_by COULD BE the Admin User, indicating that this action/InstanceHistory was
                #       executed by the administrator.. Future Release Idea.
                _execute_provider_action(identity, identity.created_by, instance, action.name)
                # NOTE: Intentionally added to allow time for
                #      the Cloud to begin 'suspend' operation
                #      before querying for the instance again.
                #TODO: Instead: Add "wait_for" change from active to any terminal, non-active state?
                wait_time = random.uniform(2, 6)
                time.sleep(wait_time)
                updated_esh = driver.get_instance(instance.id)
                convert_esh_instance(
                    driver, updated_esh,
                    identity.provider.uuid,
                    identity.uuid,
                    user)
        except Exception, e:
            # Raise ANY exception that doesn't say
            # 'This instance is already in the requested VM state'
            #NOTE: This is OpenStack specific
            if 'in vm_state' not in e.message:
                raise
Beispiel #2
0
    def get(self, request, provider_uuid, identity_uuid, instance_id):
        """
        Authentication Required, get instance details.
        """
        user = request.user
        # NOTE: This 'Scheme' should be used across
        #       the ENTIRE API v1 (Machines, Volumes, Sizes)
        # NOTE: Especially the part below, where you end date
        #       all the things that are 'inactive'
        try:
            provider = Provider.objects.get(uuid=provider_uuid)
            if not provider.is_current():
                raise ProviderNotActive(provider)
        except Provider.DoesNotExist:
            return invalid_creds(provider_uuid, identity_uuid)
        except ProviderNotActive as pna:
            return inactive_provider(pna)

        # Cleared provider testing -- ready for driver prep.
        try:
            esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
            if not esh_driver:
                return invalid_creds(provider_uuid, identity_uuid)
            logger.info("InstanceQuery Looking for %s" % instance_id)
            esh_instance = esh_driver.get_instance(instance_id)
            logger.info("InstanceQuery Found instance %s" % esh_instance)
        except (socket_error, ConnectionFailure):
            logger.exception("Connection failure prevented InstanceQuery")
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            logger.exception("Invalid credentialsprevented InstanceQuery")
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT,
                                    str(exc.message))

        # NOTE: Especially THIS part below, where you end date all the
        #       things that are 'inactive'
        if not esh_instance:
            try:
                core_inst = CoreInstance.objects.get(
                    provider_alias=instance_id,
                    source__provider__uuid=provider_uuid,
                    created_by_identity__uuid=identity_uuid)
                core_inst.end_date_all()
            except CoreInstance.DoesNotExist:
                pass
            return instance_not_found(instance_id)

        core_instance = convert_esh_instance(esh_driver, esh_instance,
                                             provider_uuid, identity_uuid,
                                             user)
        serialized_data = InstanceSerializer(
            core_instance,
            context={"request": request}).data
        response = Response(serialized_data)
        response['Cache-Control'] = 'no-cache'
        return response
Beispiel #3
0
def update_status(esh_driver, instance_id, provider_id, identity_id, user):
    #Grab a new copy of the instance
    instance_list_method = esh_driver.list_instances

    if AccountProvider.objects.filter(identity__id=identity_id):
        # Instance list method changes when using the OPENSTACK provider
        instance_list_method = esh_driver.list_all_instances

    try:
        esh_instance_list = instance_list_method()
    except InvalidCredsError:
        return invalid_creds(provider_id, identity_id)

    esh_instance = [instance for instance in esh_instance_list if
                    instance.id == instance_id]
    esh_instance = esh_instance[0]

    #Convert & Update based on new status change
    core_instance = convert_esh_instance(esh_driver,
                                         esh_instance,
                                         provider_id,
                                         identity_id,
                                         user)
    core_instance.update_history(
        core_instance.esh.extra['status'],
        core_instance.esh.extra.get('task'))
Beispiel #4
0
 def get(self, request, provider_uuid, identity_uuid):
     """
     Returns a list of all instances
     """
     user = request.user
     esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     identity = Identity.objects.get(uuid=identity_uuid)
     try:
         esh_instance_list = get_cached_instances(identity=identity)
     except MalformedResponseError:
         return malformed_response(provider_uuid, identity_uuid)
     except (socket_error, ConnectionFailure):
         return connection_failure(provider_uuid, identity_uuid)
     except InvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     core_instance_list = [convert_esh_instance(esh_driver,
                                                inst,
                                                provider_uuid,
                                                identity_uuid,
                                                user)
                           for inst in esh_instance_list]
     # TODO: Core/Auth checks for shared instances
     serialized_data = InstanceSerializer(core_instance_list,
                                          context={"request": request},
                                          many=True).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #5
0
    def delete(self, request, provider_id, identity_id, instance_id):
        user = request.user
        esh_driver = prepare_driver(request, identity_id)

        try:
            esh_instance = esh_driver.get_instance(instance_id)
            if not esh_instance:
                return instance_not_found(instance_id)
            task.destroy_instance_task(esh_instance, identity_id)
            existing_instance = esh_driver.get_instance(instance_id)
            if existing_instance:
                #Instance will be deleted soon...
                esh_instance = existing_instance
                if esh_instance.extra\
                   and 'task' not in esh_instance.extra:
                    esh_instance.extra['task'] = 'queueing delete'
            core_instance = convert_esh_instance(esh_driver, esh_instance,
                                                 provider_id, identity_id,
                                                 user)
            if core_instance:
                core_instance.end_date_all()
            serialized_data = InstanceSerializer(core_instance).data
            response = Response(serialized_data, status=status.HTTP_200_OK)
            response['Cache-Control'] = 'no-cache'
            return response
        except InvalidCredsError:
            return invalid_creds(provider_id, identity_id)
Beispiel #6
0
    def put(self, request, provider_id, identity_id, instance_id):
        """
        TODO:
            Options for put
            - Instance status change (suspend,resume,etc.)
            - DB changes (Name, tags)
        """
        user = request.user
        data = request.DATA
        #Ensure item exists on the server first
        esh_driver = prepare_driver(request, identity_id)
        try:
            esh_instance = esh_driver.get_instance(instance_id)
        except InvalidCredsError:
            return invalid_creds(provider_id, identity_id)

        if not esh_instance:
            return instance_not_found(instance_id)

        #Gather the DB related item and update
        core_instance = convert_esh_instance(esh_driver, esh_instance,
                                           provider_id, identity_id, user)
        serializer = InstanceSerializer(core_instance, data=data)
        if serializer.is_valid():
            logger.info('metadata = %s' % data)
            update_instance_metadata(esh_driver, esh_instance, data)
            serializer.save()
            response = Response(serializer.data)
            logger.info('data = %s' % serializer.data)
            response['Cache-Control'] = 'no-cache'
            return response
        else:
            return Response(serializer.errors, status=status.HTTP_400)
Beispiel #7
0
    def patch(self, request, provider_id, identity_id, instance_id):
        """
        """
        user = request.user
        data = request.DATA
        #Ensure item exists on the server first
        esh_driver = prepare_driver(request, identity_id)
        try:
            esh_instance = esh_driver.get_instance(instance_id)
        except InvalidCredsError:
            return invalid_creds(provider_id, identity_id)

        if not esh_instance:
            return instance_not_found(instance_id)

        #Gather the DB related item and update
        core_instance = convert_esh_instance(esh_driver, esh_instance,
                                           provider_id, identity_id, user)
        serializer = InstanceSerializer(core_instance, data=data, partial=True)
        if serializer.is_valid():
            logger.info('metadata = %s' % data)
            update_instance_metadata(esh_driver, esh_instance, data)
            serializer.save()
            response = Response(serializer.data)
            logger.info('data = %s' % serializer.data)
            response['Cache-Control'] = 'no-cache'
            return response
        else:
            return Response(
                serializer.errors,
                status=status.HTTP_400_BAD_REQUEST)
Beispiel #8
0
def over_allocation_test(identity, esh_instances):
    from api import get_esh_driver
    from core.models.instance import convert_esh_instance
    from atmosphere import settings
    over_allocated, time_diff = check_over_allocation(
        identity.created_by.username, identity.id,
        time_period=relativedelta(day=1, months=1))
    logger.info("Overallocation Test: %s - %s - %s\tInstances:%s"
                % (identity.created_by.username, over_allocated, time_diff, esh_instances))
    if not over_allocated:
        # Nothing changed, bail.
        return False
    if settings.DEBUG:
        logger.info('Do not enforce allocations in DEBUG mode')
        return False
    driver = get_esh_driver(identity)
    running_instances = []
    for instance in esh_instances:
        #Suspend active instances, update the task in the DB
        try:
            if driver._is_active_instance(instance):
                driver.suspend_instance(instance)
        except Exception, e:
            if 'in vm_state suspended' not in e.message:
                raise
        updated_esh = driver.get_instance(instance.id)
        updated_core = convert_esh_instance(driver, updated_esh,
                                            identity.provider.id,
                                            identity.id,
                                            identity.created_by)
        running_instances.append(updated_core)
Beispiel #9
0
def monitor_instances_for_user(provider, username, instances):
    from core.models.instance import convert_esh_instance
    from api import get_esh_driver
    try:
        user = AtmosphereUser.objects.get(username=username)
        #TODO: When user->group is no longer true,
        # we will need to modify this..
        group = Group.objects.get(name=user.username)
        ident = user.identity_set.get(provider=provider)
        im = ident.identitymembership_set.get(member=group)
        #NOTE: Couples with API, probably want this in
        # service/driver
        driver = get_esh_driver(ident)
        core_instances = []
        #NOTE: We are converting them so they will
        # be picked up as core models for the 'over_allocation_test'
        for instance in instances:
            c_inst = convert_esh_instance(
                    driver, instance,
                    ident.provider.id, ident.id, ident.created_by)
            core_instances.append(c_inst)
        over_allocation = over_allocation_test(im.identity,
                                               instances)
        core_instances = user.instance_set.filter(
                provider_machine__provider=provider,
                end_date=None)
        core_instances_ident = ident.instance_set.filter(end_date=None)
        update_instances(driver, im.identity, instances, core_instances)
    except:
        logger.exception("Unable to monitor User:%s on Provider:%s"
                         % (username,provider))
Beispiel #10
0
    def delete(self, request, provider_id, identity_id, instance_id):
        """Authentication Required, TERMINATE the instance.

        Be careful, there is no going back once you've deleted an instance.
        """
        user = request.user
        esh_driver = prepare_driver(request, provider_id, identity_id)
        if not esh_driver:
            return invalid_creds(provider_id, identity_id)
        try:
            esh_instance = esh_driver.get_instance(instance_id)
            if not esh_instance:
                return instance_not_found(instance_id)
            task.destroy_instance_task(esh_instance, identity_id)
            existing_instance = esh_driver.get_instance(instance_id)
            if existing_instance:
                #Instance will be deleted soon...
                esh_instance = existing_instance
                if esh_instance.extra\
                   and 'task' not in esh_instance.extra:
                    esh_instance.extra['task'] = 'queueing delete'
            core_instance = convert_esh_instance(esh_driver, esh_instance,
                                                 provider_id, identity_id,
                                                 user)
            if core_instance:
                core_instance.end_date_all()
            else:
                logger.warn("Unable to find core instance %s." % (instance_id))
            serialized_data = InstanceSerializer(core_instance,
                                                 context={"request":request}).data
            response = Response(serialized_data, status=status.HTTP_200_OK)
            response['Cache-Control'] = 'no-cache'
            return response
        except InvalidCredsError:
            return invalid_creds(provider_id, identity_id)
Beispiel #11
0
    def get(self, request, provider_id, identity_id):
        """
        Returns a list of all instances
        """
        user = request.user
        esh_driver = prepare_driver(request, provider_id, identity_id)
        if not esh_driver:
            return invalid_creds(provider_id, identity_id)

        instance_list_method = esh_driver.list_instances

        if AccountProvider.objects.filter(identity__id=identity_id):
            # Instance list method changes when using the OPENSTACK provider
            instance_list_method = esh_driver.list_all_instances
        try:
            esh_instance_list = instance_list_method()
        except InvalidCredsError:
            return invalid_creds(provider_id, identity_id)

        core_instance_list = [convert_esh_instance(esh_driver,
                                                   inst,
                                                   provider_id,
                                                   identity_id,
                                                   user)
                              for inst in esh_instance_list]

        #TODO: Core/Auth checks for shared instances

        serialized_data = InstanceSerializer(core_instance_list,
                                             context={"request":request},
                                             many=True).data
        response = Response(serialized_data)
        response['Cache-Control'] = 'no-cache'
        return response
Beispiel #12
0
 def get(self, request, provider_id, identity_id, instance_id):
     """
     Authentication Required, get instance details.
     """
     user = request.user
     esh_driver = prepare_driver(request, provider_id, identity_id)
     if not esh_driver:
         return invalid_creds(provider_id, identity_id)
     esh_instance = esh_driver.get_instance(instance_id)
     if not esh_instance:
         try:
             core_inst = CoreInstance.objects.get(
                 provider_alias=instance_id,
                 provider_machine__provider__id=provider_id,
                 created_by_identity__id=identity_id)
             core_inst.end_date_all()
         except CoreInstance.DoesNotExist:
             pass
         return instance_not_found(instance_id)
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_id, identity_id, user)
     serialized_data = InstanceSerializer(core_instance,
                                          context={"request":request}).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #13
0
def get_core_instance(request, provider_id, identity_id, instance_id):
    user = request.user
    esh_driver = prepare_driver(request, provider_id, identity_id)
    esh_instance = get_esh_instance(request, provider_id, identity_id, instance_id)
    core_instance = convert_esh_instance(esh_driver, esh_instance,
                                         provider_id, identity_id, user)
    return core_instance
Beispiel #14
0
 def put(self, request, provider_id, identity_id, instance_id):
     """Authentication Required, update metadata about the instance"""
     user = request.user
     data = request.DATA
     #Ensure item exists on the server first
     esh_driver = prepare_driver(request, provider_id, identity_id)
     if not esh_driver:
         return invalid_creds(provider_id, identity_id)
     esh_instance = esh_driver.get_instance(instance_id)
     if not esh_instance:
         return instance_not_found(instance_id)
     #Gather the DB related item and update
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_id, identity_id, user)
     serializer = InstanceSerializer(core_instance, data=data,
                                     context={"request":request})
     if serializer.is_valid():
         logger.info('metadata = %s' % data)
         update_instance_metadata(esh_driver, esh_instance, data)
         serializer.save()
         response = Response(serializer.data)
         logger.info('data = %s' % serializer.data)
         response['Cache-Control'] = 'no-cache'
         return response
     else:
         return Response(serializer.errors, status=status.HTTP_400)
Beispiel #15
0
def monitor_instances_for(provider_id, users=None,
                          print_logs=False, check_allocations=False, start_date=None, end_date=None):
    """
    Run the set of tasks related to monitoring instances for a provider.
    Optionally, provide a list of usernames to monitor
    While debugging, print_logs=True can be very helpful.
    start_date and end_date allow you to search a 'non-standard' window of time.
    """
    provider = Provider.objects.get(id=provider_id)

    # For now, lets just ignore everything that isn't openstack.
    if 'openstack' not in provider.type.name.lower():
        return

    instance_map = _get_instance_owner_map(provider, users=users)

    if print_logs:
        import logging
        import sys
        consolehandler = logging.StreamHandler(sys.stdout)
        consolehandler.setLevel(logging.DEBUG)
        celery_logger.addHandler(consolehandler)

    # DEVNOTE: Potential slowdown running multiple functions
    # Break this out when instance-caching is enabled
    running_total = 0
    for username in sorted(instance_map.keys()):
        running_instances = instance_map[username]
        running_total += len(running_instances)
        identity = _get_identity_from_tenant_name(provider, username)
        if identity and running_instances:
            try:
                driver = get_cached_driver(identity=identity)
                core_running_instances = [
                    convert_esh_instance(
                        driver,
                        inst,
                        identity.provider.uuid,
                        identity.uuid,
                        identity.created_by) for inst in running_instances]
            except Exception as exc:
                celery_logger.exception(
                    "Could not convert running instances for %s" %
                    username)
                continue
        else:
            # No running instances.
            core_running_instances = []
        # Using the 'known' list of running instances, cleanup the DB
        core_instances = _cleanup_missing_instances(
            identity,
            core_running_instances)
        if check_allocations:
            allocation_result = user_over_allocation_enforcement(
                provider, username,
                print_logs, start_date, end_date)
    if print_logs:
        celery_logger.removeHandler(consolehandler)
    return running_total
    def delete(self, request, provider_uuid, identity_uuid, instance_id):
        """Authentication Required, TERMINATE the instance.

        Be careful, there is no going back once you've deleted an instance.
        """
        user = request.user
        esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        try:
            esh_instance = esh_driver.get_instance(instance_id)
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except InvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. " "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT, str(exc.message))
        try:
            # Test that there is not an attached volume BEFORE we destroy

            task.destroy_instance_task(user, esh_instance, identity_uuid)

            invalidate_cached_instances(identity=Identity.objects.get(uuid=identity_uuid))

            existing_instance = esh_driver.get_instance(instance_id)
            if existing_instance:
                # Instance will be deleted soon...
                esh_instance = existing_instance
                if esh_instance.extra and "task" not in esh_instance.extra:
                    esh_instance.extra["task"] = "queueing delete"
        except VolumeAttachConflict as exc:
            message = exc.message
            return failure_response(status.HTTP_409_CONFLICT, message)
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except InvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. " "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT, str(exc.message))

        try:
            core_instance = convert_esh_instance(esh_driver, esh_instance, provider_uuid, identity_uuid, user)
            if core_instance:
                core_instance.end_date_all()
            else:
                logger.warn("Unable to find core instance %s." % (instance_id))
            serialized_data = InstanceSerializer(core_instance, context={"request": request}).data
            response = Response(serialized_data, status=status.HTTP_200_OK)
            response["Cache-Control"] = "no-cache"
            return response
        except (Identity.DoesNotExist) as exc:
            return failure_response(status.HTTP_400_BAD_REQUEST, "Invalid provider_uuid or identity_uuid.")
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except InvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
Beispiel #17
0
def get_core_instances(identity_id):
    identity = CoreIdentity.objects.get(id=identity_id)
    driver = get_esh_driver(identity)
    instances = driver.list_instances()
    core_instances = [
        convert_esh_instance(driver, esh_instance, identity.provider.id, identity.id, identity.created_by)
        for esh_instance in instances
    ]
    return core_instances
Beispiel #18
0
def monitor_instances_for(provider_id, users=None,
                          print_logs=False, start_date=None, end_date=None):
    """
    Run the set of tasks related to monitoring instances for a provider.
    Optionally, provide a list of usernames to monitor
    While debugging, print_logs=True can be very helpful.
    start_date and end_date allow you to search a 'non-standard' window of time.
    """
    provider = Provider.objects.get(id=provider_id)

    # For now, lets just ignore everything that isn't openstack.
    if 'openstack' not in provider.type.name.lower():
        return
    instance_map = _get_instance_owner_map(provider, users=users)

    if print_logs:
        console_handler = _init_stdout_logging()
    seen_instances = []
    # DEVNOTE: Potential slowdown running multiple functions
    # Break this out when instance-caching is enabled
    if not settings.ENFORCING:
        celery_logger.debug('Settings dictate allocations are NOT enforced')
    for tenant_name in sorted(instance_map.keys()):
        running_instances = instance_map[tenant_name]
        identity = _get_identity_from_tenant_name(provider, tenant_name)
        if identity and running_instances:
            try:
                driver = get_cached_driver(identity=identity)
                core_running_instances = [
                    convert_esh_instance(
                        driver,
                        inst,
                        identity.provider.uuid,
                        identity.uuid,
                        identity.created_by) for inst in running_instances]
                seen_instances.extend(core_running_instances)
            except Exception as exc:
                celery_logger.exception(
                    "Could not convert running instances for %s" %
                    tenant_name)
                continue
        else:
            # No running instances.
            core_running_instances = []
        # Using the 'known' list of running instances, cleanup the DB
        core_instances = _cleanup_missing_instances(
            identity,
            core_running_instances)
    if print_logs:
        _exit_stdout_logging(console_handler)
    # return seen_instances  NOTE: this has been commented out to avoid PicklingError!
    # TODO: Uncomment the above, Determine what _we can return_ and return that instead....
    return
Beispiel #19
0
 def put(self, request, provider_uuid, identity_uuid, instance_id):
     """Authentication Required, update metadata about the instance"""
     user = request.user
     data = request.data
     # Ensure item exists on the server first
     esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     if not can_use_instance(user, instance_id, leader_required=True):
         return member_action_forbidden(user.username, instance_id)
     try:
         esh_instance = esh_driver.get_instance(instance_id)
     except (socket_error, ConnectionFailure):
         return connection_failure(provider_uuid, identity_uuid)
     except LibcloudInvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     except Exception as exc:
         logger.exception("Encountered a generic exception. "
                          "Returning 409-CONFLICT")
         return failure_response(status.HTTP_409_CONFLICT,
                                 str(exc.message))
     if not esh_instance:
         return instance_not_found(instance_id)
     # Gather the DB related item and update
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_uuid, identity_uuid,
                                          user)
     serializer = InstanceSerializer(core_instance, data=data,
                                     context={"request": request})
     identity = Identity.objects.get(uuid=identity_uuid)
     if serializer.is_valid():
         logger.info('metadata = %s' % data)
         #NOTE: We shouldn't allow 'full replacement' of metadata..
         # We should also validate against potentional updating of 'atmo-used metadata'
         update_metadata.s(esh_driver.__class__, esh_driver.provider, esh_driver.identity, esh_instance.id,
                           data, replace_metadata=False).apply()
         new_instance = serializer.save()
         boot_scripts = data.pop('boot_scripts', [])
         if boot_scripts:
             new_instance = _save_scripts_to_instance(new_instance,
                                                      boot_scripts)
             serializer = InstanceSerializer(
                 new_instance,
                 context={"request": request})
         invalidate_cached_instances(identity=identity)
         response = Response(serializer.data)
         logger.info('data = %s' % serializer.data)
         response['Cache-Control'] = 'no-cache'
         return response
     else:
         return Response(serializer.errors,
                         status=status.HTTP_400_BAD_REQUEST)
Beispiel #20
0
def launch_instance(user, provider_id, identity_id,
                    size_alias, machine_alias, **kwargs):
    """
    Required arguments will launch the instance, extras will do
    provider-specific modifications.

    Test the quota, Launch the instance,
    creates a core repr and updates status.

    returns a core_instance object after updating core DB.
    """
    now_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    if machine_alias:
        alias = "machine,%s" % machine_alias
    elif 'volume_alias' in kwargs:
        alias = "boot_volume,%s" % kwargs['volume_alias']
    else:
        raise Exception("Not enough data to launch: "
                        "volume_alias/machine_alias is missing")
    status_logger.debug("%s,%s,%s,%s,%s,%s"
                 % (now_time, user, "No Instance", alias, size_alias,
                    "Request Received"))
    core_identity = CoreIdentity.objects.get(id=identity_id)

    esh_driver = get_esh_driver(core_identity, user)
    size = esh_driver.get_size(size_alias)

    #May raise SizeNotAvailable
    check_size(size, provider_id)

    #May raise OverQuotaError or OverAllocationError
    check_quota(user.username, identity_id, size)

    #May raise InvalidCredsError
    (esh_instance, token, password) = launch_esh_instance(esh_driver,
            machine_alias, size_alias, core_identity, **kwargs)
    #Convert esh --> core
    core_instance = convert_esh_instance(
        esh_driver, esh_instance, provider_id, identity_id,
        user, token, password)
    esh_size = esh_driver.get_size(esh_instance.size.id)
    core_size = convert_esh_size(esh_size, provider_id)
    core_instance.update_history(
        core_instance.esh.extra['status'],
        core_size,
        #3rd arg is task OR tmp_status
        core_instance.esh.extra.get('task') or
        core_instance.esh.extra.get('metadata', {}).get('tmp_status'),
        first_update=True)

    return core_instance
Beispiel #21
0
def _complete_launch_instance(driver, identity, instance, user, token, password, deploy=True):
    from service import task
    #Create the Core/DB for instance
    core_instance = convert_esh_instance(
        driver, instance, identity.provider.uuid, identity.uuid,
        user, token, password)
    # call async task to deploy to instance.
    task.deploy_init_task(driver, instance, identity, user.username,
                          password, token, deploy=deploy)
    #Update InstanceStatusHistory
    _first_update(driver, identity, core_instance, instance)
    #Invalidate and return
    invalidate_cached_instances(identity=identity)
    return core_instance
Beispiel #22
0
    def patch(self, request, provider_uuid, identity_uuid, instance_id):
        """Authentication Required, update metadata about the instance"""
        user = request.user
        data = request.data
        esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        try:
            esh_instance = esh_driver.get_instance(instance_id)
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except InvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT,
                                    str(exc.message))
        if not esh_instance:
            return instance_not_found(instance_id)
        # Gather the DB related item and update
        core_instance = convert_esh_instance(esh_driver, esh_instance,
                                             provider_uuid, identity_uuid,
                                             user)
        serializer = InstanceSerializer(
            core_instance, data=data,
            context={"request": request}, partial=True)
        identity = Identity.objects.get(uuid=identity_uuid)
        provider = identity.provider

        if serializer.is_valid():
            logger.info('metadata = %s' % data)

            driver_class = esh_driver.__class__
            update_metadata.s(driver_class, provider, identity, esh_instance.id,
                              data, replace_metadata=False).apply()
            instance = serializer.save()
            boot_scripts = data.pop('boot_scripts', [])
            if boot_scripts:
                _save_scripts_to_instance(instance, boot_scripts)
            invalidate_cached_instances(identity=identity)
            response = Response(serializer.data)
            logger.info('data = %s' % serializer.data)
            response['Cache-Control'] = 'no-cache'
            return response
        else:
            return Response(
                serializer.errors,
                status=status.HTTP_400_BAD_REQUEST)
Beispiel #23
0
 def put(self, request, provider_uuid, identity_uuid, instance_id):
     """Authentication Required, update metadata about the instance"""
     user = request.user
     data = request.DATA
     # Ensure item exists on the server first
     esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     try:
         esh_instance = esh_driver.get_instance(instance_id)
     except ConnectionFailure:
         return connection_failure(provider_uuid, identity_uuid)
     except InvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     except Exception as exc:
         logger.exception("Encountered a generic exception. "
                          "Returning 409-CONFLICT")
         return failure_response(status.HTTP_409_CONFLICT,
                                 str(exc.message))
     if not esh_instance:
         return instance_not_found(instance_id)
     # Gather the DB related item and update
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_uuid, identity_uuid,
                                          user)
     serializer = InstanceSerializer(core_instance, data=data,
                                     context={"request": request})
     if serializer.is_valid():
         logger.info('metadata = %s' % data)
         update_instance_metadata(esh_driver, esh_instance, data)
         serializer.save()
         new_instance = serializer.object
         boot_scripts = data.pop('boot_scripts', [])
         if boot_scripts:
             new_instance = _save_scripts_to_instance(new_instance,
                                                      boot_scripts)
             serializer = InstanceSerializer(
                 new_instance,
                 context={"request": request})
         invalidate_cached_instances(
                 identity=Identity.objects.get(
                     uuid=identity_uuid))
         response = Response(serializer.data)
         logger.info('data = %s' % serializer.data)
         response['Cache-Control'] = 'no-cache'
         return response
     else:
         return Response(serializer.errors,
                         status=status.HTTP_400_BAD_REQUEST)
Beispiel #24
0
def current_instance_time(user, instances, identity_id, delta_time):
    """
    Add all running instances to core, so that the database is up to date
    before calling 'core_instance_time'
    """
    from api import get_esh_driver
    ident = Identity.objects.get(id=identity_id)
    driver = get_esh_driver(ident)
    core_instance_list = [
            convert_esh_instance(driver, inst,
                                 ident.provider.id, ident.id, user)
                          for inst in instances]
    #All instances that don't have an end-date should be
    #included, even if all of their time is not.
    time_used = core_instance_time(user, ident.id, delta_time, running=core_instance_list)
    return time_used
    def get(self, request, provider_uuid, identity_uuid, instance_id):
        """
        Authentication Required, get instance details.
        """
        user = request.user
        # NOTE: This 'Scheme' should be used across
        #       the ENTIRE API v1 (Machines, Volumes, Sizes)
        # NOTE: Especially the part below, where you end date
        #       all the things that are 'inactive'
        try:
            provider = Provider.objects.get(uuid=provider_uuid)
        except Provider.DoesNotExist:
            return invalid_creds(provider_uuid, identity_uuid)
        if provider.is_active():
            esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
            try:
                esh_instance = esh_driver.get_instance(instance_id)
            except (socket_error, ConnectionFailure):
                return connection_failure(provider_uuid, identity_uuid)
            except InvalidCredsError:
                return invalid_creds(provider_uuid, identity_uuid)
            except Exception as exc:
                logger.exception("Encountered a generic exception. " "Returning 409-CONFLICT")
                return failure_response(status.HTTP_409_CONFLICT, str(exc.message))
        else:
            esh_instance = None

        # NOTE: Especially THIS part below, where you end date all the
        #       things that are 'inactive'
        if not esh_instance:
            try:
                core_inst = CoreInstance.objects.get(
                    provider_alias=instance_id,
                    source__provider__uuid=provider_uuid,
                    created_by_identity__uuid=identity_uuid,
                )
                core_inst.end_date_all()
            except CoreInstance.DoesNotExist:
                pass
            return instance_not_found(instance_id)

        core_instance = convert_esh_instance(esh_driver, esh_instance, provider_uuid, identity_uuid, user)
        serialized_data = InstanceSerializer(core_instance, context={"request": request}).data
        response = Response(serialized_data)
        response["Cache-Control"] = "no-cache"
        return response
Beispiel #26
0
 def get(self, request, provider_id, identity_id, instance_id):
     """
     Return the object belonging to this instance ID
     TODO: Filter out instances you shouldnt see (permissions..)
     """
     user = request.user
     esh_driver = prepare_driver(request, provider_id, identity_id)
     if not esh_driver:
         return invalid_creds(provider_id, identity_id)
     esh_instance = esh_driver.get_instance(instance_id)
     if not esh_instance:
         return instance_not_found(instance_id)
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_id, identity_id, user)
     serialized_data = InstanceSerializer(core_instance).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #27
0
 def get(self, request, provider_id, identity_id, instance_id):
     """
     Authentication Required, get instance details.
     """
     user = request.user
     esh_driver = prepare_driver(request, provider_id, identity_id)
     if not esh_driver:
         return invalid_creds(provider_id, identity_id)
     esh_instance = esh_driver.get_instance(instance_id)
     if not esh_instance:
         return instance_not_found(instance_id)
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_id, identity_id, user)
     serialized_data = InstanceSerializer(core_instance,
                                          context={"request":request}).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #28
0
def update_status(esh_driver, instance_id, provider_id, identity_id, user):
    """
    All that this method really does is:
    * Query for the instance
    * call 'convert_esh_instance'
    Converting the instance internally updates the status history..
    But it makes more sense to call this function in the code..
    """
    # Grab a new copy of the instance

    if AccountProvider.objects.filter(identity__id=identity_id):
        esh_instance = admin_get_instance(esh_driver, instance_id)
    else:
        esh_instance = esh_driver.get_instance(instance_id)
    if not esh_instance:
        return None
    # Convert & Update based on new status change
    core_instance = convert_esh_instance(esh_driver, esh_instance, provider_id, identity_id, user)
Beispiel #29
0
    def post(self, request, provider_id, identity_id, volume_id=None):
        user = request.user
        data = request.DATA

        missing_keys = valid_launch_data(data)
        if missing_keys:
            return keys_not_found(missing_keys)

        esh_driver = prepare_driver(request, provider_id, identity_id)
        if not esh_driver:
            return invalid_creds(provider_id, identity_id)

        source = None
        name = data.pop('name')
        size_id = data.pop('size')

        (source_type, get_source, source_id) = self._select_source(esh_driver,
                                                                   data)
        if not get_source:
            return failure_response(
                status.HTTP_400_BAD_REQUEST,
                'Source could not be acquired. Did you send: ['
                'snapshot_id/volume_id/image_id] ?')
        source = get_source(source_id)
        if not source:
            return failure_response(
                status.HTTP_404_NOT_FOUND,
                "%s %s does not exist"
                % (source_type.title(), source_id))
        size = esh_driver.get_size(size_id)
        if not size:
            return failure_response(
                status.HTTP_404_NOT_FOUND,
                "Size %s does not exist"
                % (size_id,))

        esh_instance = boot_volume(esh_driver, identity_id, name,
                                   size, source, source_type, **data)
        core_instance = convert_esh_instance(esh_driver, esh_instance,
                                             provider_id, identity_id, user)
        serialized_data = InstanceSerializer(core_instance,
                                             context={'request': request}).data
        response = Response(serialized_data)
        return response
Beispiel #30
0
 def get(self, request, provider_uuid, identity_uuid):
     """
     Returns a list of all instances
     """
     user = request.user
     try:
         esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     except ProviderNotActive as pna:
         return inactive_provider(pna)
     except Exception as e:
         return failure_response(
             status.HTTP_409_CONFLICT,
             e.message)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     identity = Identity.objects.get(uuid=identity_uuid)
     # Probably redundant
     if not user.can_use_identity(identity.id):
         return invalid_creds(provider_uuid, identity_uuid)
     try:
         esh_instance_list = get_cached_instances(identity=identity)
     except MalformedResponseError:
         return malformed_response(provider_uuid, identity_uuid)
     except (socket_error, ConnectionFailure):
         return connection_failure(provider_uuid, identity_uuid)
     except InvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     core_instance_list = [convert_esh_instance(esh_driver,
                                                inst,
                                                provider_uuid,
                                                identity_uuid,
                                                user)
                           for inst in esh_instance_list]
     # TODO: Core/Auth checks for shared instances
     serialized_data = InstanceSerializer(core_instance_list,
                                          context={"request": request},
                                          many=True).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #31
0
def launch_instance(user, provider_id, identity_id,
                    size_alias, machine_alias, **kwargs):
    """
    Required arguments will launch the instance, extras will do
    provider-specific modifications.

    Test the quota, Launch the instance,
    creates a core repr and updates status.

    returns a core_instance object after updating core DB.
    """

    core_identity = CoreIdentity.objects.get(id=identity_id)

    esh_driver = get_esh_driver(core_identity, user)
    size = esh_driver.get_size(size_alias)

    #May raise SizeNotAvailable
    check_size(size, provider_id)

    #May raise OverQuotaError or OverAllocationError
    check_quota(user.username, identity_id, size)

    #May raise InvalidCredsError
    (esh_instance, token, password) = launch_esh_instance(esh_driver, machine_alias,
                                                size_alias, core_identity,
                                                **kwargs)
    #Convert esh --> core
    core_instance = convert_esh_instance(
        esh_driver, esh_instance, provider_id, identity_id,
        user, token, password)
    core_instance.update_history(
        core_instance.esh.extra['status'],
        #2nd arg is task OR tmp_status
        core_instance.esh.extra.get('task') or
        core_instance.esh.extra.get('metadata', {}).get('tmp_status'),
        first_update=True)

    return core_instance
Beispiel #32
0
 def get(self, request, provider_uuid, identity_uuid):
     """
     Returns a list of all instances
     """
     user = request.user
     try:
         esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     except ProviderNotActive as pna:
         return inactive_provider(pna)
     except Exception as e:
         return failure_response(status.HTTP_409_CONFLICT, e.message)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     identity = Identity.objects.get(uuid=identity_uuid)
     # Probably redundant
     if not user.can_use_identity(identity.id):
         return invalid_creds(provider_uuid, identity_uuid)
     try:
         esh_instance_list = get_cached_instances(identity=identity)
     except LibcloudBadResponseError:
         return malformed_response(provider_uuid, identity_uuid)
     except (socket_error, ConnectionFailure):
         return connection_failure(provider_uuid, identity_uuid)
     except LibcloudInvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     core_instance_list = [
         convert_esh_instance(esh_driver, inst, provider_uuid,
                              identity_uuid, user)
         for inst in esh_instance_list
     ]
     # TODO: Core/Auth checks for shared instances
     serialized_data = InstanceSerializer(core_instance_list,
                                          context={
                                              "request": request
                                          },
                                          many=True).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #33
0
def update_status(esh_driver, instance_id, provider_uuid, identity_uuid, user):
    """
    All that this method really does is:
    * Query for the instance
    * call 'convert_esh_instance'
    Converting the instance internally updates the status history..
    But it makes more sense to call this function in the code..
    """
    #Grab a new copy of the instance

    if AccountProvider.objects.filter(identity__uuid=identity_uuid):
        esh_instance = admin_get_instance(esh_driver, instance_id)
    else:
        esh_instance = esh_driver.get_instance(instance_id)
    if not esh_instance:
        return None
    #Convert & Update based on new status change
    core_instance = convert_esh_instance(esh_driver,
                                         esh_instance,
                                         provider_uuid,
                                         identity_uuid,
                                         user)
Beispiel #34
0
 def get(self, request, provider_uuid, identity_uuid, instance_id):
     """
     Authentication Required, get instance details.
     """
     user = request.user
     esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     try:
         esh_instance = esh_driver.get_instance(instance_id)
     except (socket_error, ConnectionFailure):
         return connection_failure(provider_uuid, identity_uuid)
     except InvalidCredsError:
         return invalid_creds(provider_uuid, identity_uuid)
     except Exception as exc:
         logger.exception("Encountered a generic exception. "
                          "Returning 409-CONFLICT")
         return failure_response(status.HTTP_409_CONFLICT,
                                 str(exc.message))
     if not esh_instance:
         try:
             core_inst = CoreInstance.objects.get(
                 provider_alias=instance_id,
                 source__provider__uuid=provider_uuid,
                 created_by_identity__uuid=identity_uuid)
             core_inst.end_date_all()
         except CoreInstance.DoesNotExist:
             pass
         return instance_not_found(instance_id)
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_uuid, identity_uuid,
                                          user)
     serialized_data = InstanceSerializer(
         core_instance,
         context={"request": request}).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #35
0
 def get(self, request, provider_id, identity_id):
     """
     Returns a list of all instances
     """
     user = request.user
     esh_driver = prepare_driver(request, provider_id, identity_id)
     if not esh_driver:
         return invalid_creds(provider_id, identity_id)
     identity = Identity.objects.get(id=identity_id)
     esh_instance_list = get_cached_instances(identity=identity)
     core_instance_list = [
         convert_esh_instance(esh_driver, inst, provider_id, identity_id,
                              user) for inst in esh_instance_list
     ]
     #TODO: Core/Auth checks for shared instances
     serialized_data = InstanceSerializer(core_instance_list,
                                          context={
                                              "request": request
                                          },
                                          many=True).data
     response = Response(serialized_data)
     response['Cache-Control'] = 'no-cache'
     return response
Beispiel #36
0
def suspend_all_instances_for(identity, user):
    driver = get_cached_driver(identity=identity)
    esh_instances = driver.list_instances()
    for instance in esh_instances:
        try:
            if driver._is_active_instance(instance):
                #Suspend active instances, update the task in the DB
                driver.suspend_instance(instance)
                #NOTE: Intentionally added to allow time for 
                #      the Cloud to begin 'suspend' operation 
                #      before querying for the instance again.
                time = random.uniform(2,6)
                time.sleep(time)
                updated_esh = driver.get_instance(instance.id)
                updated_core = convert_esh_instance(
                    driver, updated_esh,
                    identity.provider.uuid,
                    identity.uuid,
                    user)
        except Exception, e:
            #Raise ANY exception that doesn't say
            #'This instance is already suspended'
            if 'in vm_state suspended' not in e.message:
                raise
Beispiel #37
0
 def put(self, request, provider_uuid, identity_uuid, instance_id):
     """Authentication Required, update metadata about the instance"""
     user = request.user
     data = request.DATA
     #Ensure item exists on the server first
     esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
     if not esh_driver:
         return invalid_creds(provider_uuid, identity_uuid)
     esh_instance = esh_driver.get_instance(instance_id)
     if not esh_instance:
         return instance_not_found(instance_id)
     #Gather the DB related item and update
     core_instance = convert_esh_instance(esh_driver, esh_instance,
                                          provider_uuid, identity_uuid, user)
     serializer = InstanceSerializer(core_instance, data=data,
                                     context={"request":request})
     if serializer.is_valid():
         logger.info('metadata = %s' % data)
         update_instance_metadata(esh_driver, esh_instance, data)
         serializer.save()
         new_instance = serializer.object
         boot_scripts = data.pop('boot_scripts', [])
         if boot_scripts:
             new_instance = _save_scripts_to_instance(new_instance, boot_scripts)
             serializer = InstanceSerializer(new_instance,
                     context={"request":request})
         invalidate_cached_instances(
                 identity=Identity.objects.get(
                     uuid=identity_uuid))
         response = Response(serializer.data)
         logger.info('data = %s' % serializer.data)
         response['Cache-Control'] = 'no-cache'
         return response
     else:
         return Response(serializer.errors,
                         status=status.HTTP_400_BAD_REQUEST)
Beispiel #38
0
    def delete(self, request, provider_uuid, identity_uuid, instance_id):
        """Authentication Required, TERMINATE the instance.

        Be careful, there is no going back once you've deleted an instance.
        """
        user = request.user
        esh_driver = prepare_driver(request, provider_uuid, identity_uuid)
        if not esh_driver:
            return invalid_creds(provider_uuid, identity_uuid)
        try:
            esh_instance = esh_driver.get_instance(instance_id)
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT, str(exc.message))
        try:
            # Test that there is not an attached volume BEFORE we destroy
            task.destroy_instance_task(user, esh_instance, identity_uuid)

            invalidate_cached_instances(identity=Identity.objects.get(
                uuid=identity_uuid))

            existing_instance = esh_driver.get_instance(instance_id)
            if existing_instance:
                # Instance will be deleted soon...
                esh_instance = existing_instance
                if esh_instance.extra\
                   and 'task' not in esh_instance.extra:
                    esh_instance.extra['task'] = 'queueing delete'
        except VolumeAttachConflict as exc:
            message = exc.message
            return failure_response(status.HTTP_409_CONFLICT, message)
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)
        except InstanceDoesNotExist as dne:
            return failure_response(
                status.HTTP_404_NOT_FOUND,
                'Instance %s no longer exists' % (dne.message, ))
        except Exception as exc:
            logger.exception("Encountered a generic exception. "
                             "Returning 409-CONFLICT")
            return failure_response(status.HTTP_409_CONFLICT, str(exc.message))

        try:
            core_instance = convert_esh_instance(esh_driver, esh_instance,
                                                 provider_uuid, identity_uuid,
                                                 user)
            if core_instance:
                core_instance.end_date_all()
            else:
                logger.warn("Unable to find core instance %s." % (instance_id))
            serialized_data = InstanceSerializer(core_instance,
                                                 context={
                                                     "request": request
                                                 }).data
            response = Response(serialized_data, status=status.HTTP_200_OK)
            response['Cache-Control'] = 'no-cache'
            return response
        except (Identity.DoesNotExist) as exc:
            return failure_response(status.HTTP_400_BAD_REQUEST,
                                    "Invalid provider_uuid or identity_uuid.")
        except (socket_error, ConnectionFailure):
            return connection_failure(provider_uuid, identity_uuid)
        except LibcloudInvalidCredsError:
            return invalid_creds(provider_uuid, identity_uuid)