def post(self, request, provider_uuid, identity_uuid, volume_id=None): user = request.user data = request.data missing_keys = valid_launch_data(data) if missing_keys: return keys_not_found(missing_keys) source = None name = data.pop('name') size_id = data.pop('size') key_name = self._select_source_key(data) if not key_name: return failure_response( status.HTTP_400_BAD_REQUEST, 'Source could not be acquired. Did you send: [' 'snapshot_id/volume_id/image_id] ?') try: core_instance = create_bootable_volume( request.user, provider_uuid, identity_uuid, name, size_id, volume_id, source_hint=key_name, **data) except Exception as exc: message = exc.message return failure_response( status.HTTP_409_CONFLICT, message) serialized_data = InstanceSerializer(core_instance, context={'request': request}).data response = Response(serialized_data) return response
def get(self, request, provider_uuid, identity_uuid, machine_id): 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) # TODO: Need to determine that identity_uuid is ALLOWED to # see machine_id. # if not covered by calling as the users driver.. esh_machine = esh_driver.get_machine(machine_id) core_machine = convert_esh_machine(esh_driver, esh_machine, provider_uuid, user) if not core_machine: return failure_response( status.HTTP_400_BAD_REQUEST, "Could not retrieve machine with ID = %s" % machine_id) if not core_machine.application_version.application.icon: return None app_icon = core_machine.application_version.application.icon image_name, image_ext = os.path.splitext(app_icon.name) return Response(app_icon.file)
def delete(self, request, provider_uuid, identity_uuid, volume_id): """ Destroys the volume and updates the DB """ user = request.user # Ensure volume exists 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) try: esh_volume = esh_driver.get_volume(volume_id) except 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_volume: return volume_not_found(volume_id) core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) # Delete the object, update the DB esh_driver.destroy_volume(esh_volume) core_volume.end_date = now() core_volume.save() # Return the object serialized_data = VolumeSerializer(core_volume, context={"request": request}).data response = Response(serialized_data) return response
def get(self, request, provider_uuid, identity_uuid, volume_id): """ """ 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) try: esh_volume = esh_driver.get_volume(volume_id) except 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_volume: try: source = InstanceSource.objects.get(identifier=volume_id, provider__uuid=provider_uuid) source.end_date = datetime.now() source.save() except (InstanceSource.DoesNotExist, CoreVolume.DoesNotExist): pass return volume_not_found(volume_id) core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) serialized_data = VolumeSerializer(core_volume, context={"request": request}).data response = Response(serialized_data) return response
def get(self, request, provider_uuid, identity_uuid, size_alias): """ Lookup the size information (Lookup using the given provider/identity) Update on server DB (If applicable) """ 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) esh_size = esh_driver.get_size(size_alias) if not esh_size: return failure_response( status.HTTP_404_NOT_FOUND, 'Size %s not found' % (size_alias,)) core_size = convert_esh_size(esh_size, provider_uuid) serialized_data = ProviderSizeSerializer(core_size).data response = Response(serialized_data) return response
def _update_machine( self, request, provider_uuid, identity_uuid, machine_id ): # TODO: Determine who is allowed to edit machines besides # core_machine.owner user = request.user data = request.data 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) esh_machine = esh_driver.get_machine(machine_id) core_machine = convert_esh_machine( esh_driver, esh_machine, provider_uuid, user ) if not user.is_staff and user is not core_machine.application_version.application.created_by: logger.warn( '%s is Non-staff/non-owner trying to update a machine' % (user.username) ) return failure_response( status.HTTP_401_UNAUTHORIZED, "Only Staff and the machine Owner " "are allowed to change machine info." ) partial_update = True if request.method == 'PATCH' else False serializer = ProviderMachineSerializer( core_machine, request_user=request.user, data=data, partial=partial_update ) if serializer.is_valid(): logger.info('metadata = %s' % data) update_machine_metadata(esh_driver, esh_machine, data) machine = serializer.save() if 'created_by_identity' in request.data: identity = machine.created_by_identity update_application_owner( core_machine.application_version.application, identity ) logger.info(serializer.data) return Response(serializer.data) return failure_response(status.HTTP_400_BAD_REQUEST, serializer.errors)
def put(self, request, provider_uuid, identity_uuid, volume_id): """ Updates DB values for volume """ user = request.user data = request.data # Ensure volume exists 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) if not can_use_volume(user, volume_id, leader_required=True): return member_action_forbidden(user.username, "Volume", volume_id) try: esh_volume = esh_driver.get_volume(volume_id) except 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_volume: return volume_not_found(volume_id) core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) serializer = VolumeSerializer(core_volume, data=data, context={'request': request}) if serializer.is_valid(): serializer.save() _update_volume_metadata( esh_driver, esh_volume, data) response = Response(serializer.data) return response else: failure_response( status.HTTP_400_BAD_REQUEST, serializer.errors)
def get(self, request, provider_uuid, identity_uuid): """ Using provider and identity, getlist of machines TODO: Cache this request """ try: request_user = request.user logger.debug("filtered_machine_list") filtered_machine_list = provider_filtered_machines(request, provider_uuid, identity_uuid, request_user) except ProviderNotActive as pna: return inactive_provider(pna) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) except LibcloudBadResponseError: return malformed_response(provider_uuid, identity_uuid) except (socket_error, ConnectionFailure): return connection_failure(provider_uuid, identity_uuid) except ObjectDoesNotExist: return invalid_provider_identity(provider_uuid, identity_uuid) except Exception as e: logger.exception("Unexpected exception for user:%s" % request_user) return failure_response(status.HTTP_409_CONFLICT, e.message) serialized_data = ProviderMachineSerializer(filtered_machine_list, request_user=request.user, many=True).data response = Response(serialized_data) return response
def get_esh_instance(request, provider_uuid, identity_uuid, instance_id): esh_driver = prepare_driver(request, provider_uuid, identity_uuid) if not esh_driver: raise LibcloudInvalidCredsError( "Provider_uuid && identity_uuid " "did not produce a valid combination") esh_instance = None 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: # End date everything 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 esh_instance
def get(self, request, provider_uuid, identity_uuid): """ """ 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) try: esh_snapshots = esh_driver._connection.ex_list_snapshots() except LibcloudBadResponseError: return malformed_response(provider_uuid, identity_uuid) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) snapshot_data = [] for ss in esh_snapshots: snapshot_data.append({ 'id': ss.id, 'name': ss.extra['name'], 'size': ss.size, 'description': ss.extra['description'], 'created': ss.extra['created'], 'status': ss.extra['status'], 'volume_id': ss.extra['volume_id'], }) response = Response(snapshot_data) return response
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
def get(self, request, provider_uuid, identity_uuid): """ Using provider and identity, getlist of machines TODO: Cache this request """ # TODO: Decide how we should pass this in (I.E. GET query string?) active = False 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) try: esh_size_list = esh_driver.list_sizes() except LibcloudBadResponseError: return malformed_response(provider_uuid, identity_uuid) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) except (socket_error, ConnectionFailure): return connection_failure(provider_uuid, identity_uuid) all_size_list = [convert_esh_size(size, provider_uuid) for size in esh_size_list] if active: all_size_list = [s for s in all_size_list if s.active()] serialized_data = ProviderSizeSerializer(all_size_list, many=True).data response = Response(serialized_data) return response
def get(self, request, provider_uuid, identity_uuid, machine_id): """ Details view for specific machine (Lookup using the given provider/identity) """ 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) # TODO: Need to determine that identity_uuid is ALLOWED to # see machine_id. if not covered by calling as the users driver.. esh_machine = esh_driver.get_machine(machine_id) core_machine = convert_esh_machine(esh_driver, esh_machine, provider_uuid, user) serialized_data = ProviderMachineSerializer( core_machine, request_user=request.user).data response = Response(serialized_data) return response
def delete(self, request, provider_uuid, identity_uuid, snapshot_id): """ Destroys the volume and updates the DB """ user = request.user # Ensure volume exists 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) if not can_use_snapshot(user, snapshot_id, leader_required=True): return member_action_forbidden(user.username, "Snapshot", snapshot_id) snapshot = esh_driver._connection.get_snapshot(snapshot_id) if not snapshot: return snapshot_not_found(snapshot_id) delete_success = esh_driver._connection.ex_delete_snapshot(snapshot) # NOTE: Always false until icehouse... # return failure_response( # status.HTTP_400_BAD_REQUEST, # % snapshot_id) return Response(status=status.HTTP_204_NO_CONTENT)
def post(self, request, provider_uuid, identity_uuid, machine_id): """ TODO: Determine who is allowed to edit machines besides core_machine.owner """ data = request.data logger.info('data = %s' % request.data) core_machine = ProviderMachine.objects.filter( provider__uuid=provider_uuid, identifier=machine_id ) if not core_machine: return failure_response( status.HTTP_400_BAD_REQUEST, "Machine id %s does not exist" % machine_id ) core_machine = core_machine.get() if core_machine.instance_source.created_by == request.user: return failure_response( status.HTTP_400_BAD_REQUEST, "You are NOT the owner of Machine id=%s " % machine_id ) if 'licenses' not in data \ or not isinstance(data['licenses'], list): return failure_response( status.HTTP_400_BAD_REQUEST, "Licenses missing from data. Expected a list of License IDs" " ex:[1,2,3,]" ) licenses = [] # Out with the old core_machine.licenses.all().delete() for license_id in data['licenses']: license = License.objects.get(id=license_id) # In with the new core_machine.licenses.add(license) # Return the new set. licenses = core_machine.licenses.all() logger.info('licenses = %s' % licenses) serialized_data = LicenseSerializer(licenses, many=True).data return Response(serialized_data, status=status.HTTP_202_ACCEPTED)
def get(self, request, instance_id): """ Authentication required, Retrieve a list of previously launched instances. """ params = request.query_params.copy() user = User.objects.filter(username=request.user) if user and len(user) > 0: user = user[0] else: return failure_response(status.HTTP_401_UNAUTHORIZED, 'Request User %s not found' % user) emulate_name = params.pop('username', None) # Support for staff users to emulate a specific user history if user.is_staff and emulate_name: emulate_name = emulate_name[0] # Querystring conversion user = User.objects.filter(username=emulate_name) if user and len(user) > 0: user = user[0] else: return failure_response(status.HTTP_401_UNAUTHORIZED, 'Emulated User %s not found' % emulate_name) # List of all instances matching user, instance_id core_instance =\ CoreInstance.objects.filter( created_by=user, provider_alias=instance_id).order_by("-start_date") if core_instance and len(core_instance) > 0: core_instance = core_instance[0] else: return failure_response(status.HTTP_401_UNAUTHORIZED, 'Instance %s not found' % instance_id) serialized_data = InstanceHistorySerializer( core_instance, context={"request": request}, many=True).data response = Response(serialized_data) response['Cache-Control'] = 'no-cache' return response
def get(self, request, provider_uuid, identity_uuid): """ Retrieves list of volumes and updates the DB """ 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) volume_list_method = esh_driver.list_volumes if AccountProvider.objects.filter(identity__uuid=identity_uuid): # Instance list method changes when using the OPENSTACK provider volume_list_method = esh_driver.list_all_volumes try: esh_volume_list = volume_list_method() except (socket_error, ConnectionFailure): return connection_failure(provider_uuid, identity_uuid) except LibcloudBadResponseError: return malformed_response(provider_uuid, identity_uuid) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) except Exception: logger.exception("Uncaught Exception in Volume list method") return failure_response( status.HTTP_500_INTERNAL_SERVER_ERROR, 'Volume list method failed. Contact support' ) core_volume_list = [ convert_esh_volume(volume, provider_uuid, identity_uuid, user) for volume in esh_volume_list ] serializer = VolumeSerializer( core_volume_list, context={'request': request}, many=True ) response = Response(serializer.data) return response
def delete(self, request, provider_uuid, identity_uuid, volume_id): """ Destroys the volume and updates the DB """ user = request.user # Ensure volume exists 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) try: esh_volume = esh_driver.get_volume(volume_id) except 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_volume: return volume_not_found(volume_id) core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) # Delete the object, update the DB esh_driver.destroy_volume(esh_volume) core_volume.end_date = now() core_volume.save() # Return the object serialized_data = VolumeSerializer(core_volume, context={ 'request': request }).data response = Response(serialized_data) return response
def get(self, request, provider_uuid, identity_uuid, volume_id): """ """ 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) try: esh_volume = esh_driver.get_volume(volume_id) except 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_volume: try: source = InstanceSource.objects.get( identifier=volume_id, provider__uuid=provider_uuid) source.end_date = datetime.now() source.save() except (InstanceSource.DoesNotExist, CoreVolume.DoesNotExist): pass return volume_not_found(volume_id) core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) serialized_data = VolumeSerializer(core_volume, context={ 'request': request }).data response = Response(serialized_data) return response
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)
def get(self, request, instance_id): """ Authentication required, Retrieve a list of previously launched instances. """ params = request.query_params.copy() user = User.objects.filter(username=request.user) if user and len(user) > 0: user = user[0] else: return failure_response(status.HTTP_401_UNAUTHORIZED, 'Request User %s not found' % user) emulate_name = params.pop('username', None) # Support for staff users to emulate a specific user history if user.is_staff and emulate_name: emulate_name = emulate_name[0] # Querystring conversion user = User.objects.filter(username=emulate_name) if user and len(user) > 0: user = user[0] else: return failure_response( status.HTTP_401_UNAUTHORIZED, 'Emulated User %s not found' % emulate_name) # List of all instances matching user, instance_id core_instance = CoreInstance.objects.filter( created_by=user, provider_alias=instance_id).order_by("-start_date") if core_instance and len(core_instance) > 0: core_instance = core_instance[0] else: return failure_response(status.HTTP_401_UNAUTHORIZED, 'Instance %s not found' % instance_id) status_history = core_instance\ .instancestatushistory_set.order_by('start_date') serialized_data = InstanceStatusHistorySerializer(status_history, many=True).data response = Response(serialized_data) response['Cache-Control'] = 'no-cache' return response
def update(self, request, pk=None, partial=False): data = request.data if not request.user.is_admin(): return failure_response( status.HTTP_403_FORBIDDEN, "Non-admin users cannot update an Identity") if not pk: return failure_response(status.HTTP_400_BAD_REQUEST, "Key required to update identity") if 'quota' not in data: return failure_response(status.HTTP_400_BAD_REQUEST, "Only 'quota' can be updated on identity") identity = Identity.objects.get(uuid=pk) SerializerCls = self.get_serializer_class() serializer = SerializerCls(identity, data=data, context={'request': self.request}) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
def get(self, request, provider_uuid, identity_uuid, size_alias): """ Lookup the size information (Lookup using the given provider/identity) Update on server DB (If applicable) """ 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) esh_size = esh_driver.get_size(size_alias) if not esh_size: return failure_response(status.HTTP_404_NOT_FOUND, 'Size %s not found' % (size_alias, )) core_size = convert_esh_size(esh_size, provider_uuid) serialized_data = ProviderSizeSerializer(core_size).data response = Response(serialized_data) return response
def get(self, request, provider_uuid, identity_uuid, snapshot_id): """ """ 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) snapshot = esh_driver._connection.get_snapshot(snapshot_id) if not snapshot: return snapshot_not_found(snapshot_id) response = Response(snapshot) return response
def delete(self, request, provider_uuid, identity_uuid, instance_id, tag_slug, *args, **kwargs): """ Remove the tag, if it is no longer in use. """ core_instance = get_core_instance(request, provider_uuid, identity_uuid, instance_id) if not core_instance: instance_not_found(instance_id) try: tag = core_instance.tags.get(name__iexact=tag_slug) except CoreTag.DoesNotExist: return failure_response(status.HTTP_404_NOT_FOUND, 'Tag %s not found on instance' % tag_slug) core_instance.tags.remove(tag) return Response(status=status.HTTP_204_NO_CONTENT)
def get(self, request, provider_uuid, identity_uuid, machine_id): """ Lookup the machine information (Lookup using the given provider/identity) Update on server (If applicable) """ core_machine = ProviderMachine.objects.filter( provider__uuid=provider_uuid, identifier=machine_id) if not core_machine: return failure_response( status.HTTP_400_BAD_REQUEST, "Machine id %s does not exist" % machine_id) core_machine = core_machine.get() licenses = core_machine.licenses.all() serialized_data = LicenseSerializer(licenses, many=True).data return Response(serialized_data, status=status.HTTP_200_OK)
def delete(self, request, provider_uuid, identity_uuid, instance_id, tag_slug, *args, **kwargs): """ Remove the tag, if it is no longer in use. """ core_instance = get_core_instance(request, provider_uuid, identity_uuid, instance_id) if not core_instance: instance_not_found(instance_id) try: tag = core_instance.tags.get(name__iexact=tag_slug) except CoreTag.DoesNotExist: return failure_response( status.HTTP_404_NOT_FOUND, 'Tag %s not found on instance' % tag_slug) core_instance.tags.remove(tag) return Response(status=status.HTTP_204_NO_CONTENT)
def delete(self, request, provider_uuid, identity_uuid, snapshot_id): """ Destroys the volume and updates the DB """ # Ensure volume exists 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) snapshot = esh_driver._connection.get_snapshot(snapshot_id) if not snapshot: return snapshot_not_found(snapshot_id) delete_success = esh_driver._connection.ex_delete_snapshot(snapshot) # NOTE: Always false until icehouse... # return failure_response( # status.HTTP_400_BAD_REQUEST, # % snapshot_id) return Response(status=status.HTTP_204_NO_CONTENT)
def get(self, request, provider_uuid, identity_uuid, instance_id, tag_slug, *args, **kwargs): """ Return the credential information for this tag """ try: core_instance = get_core_instance(request, provider_uuid, identity_uuid, instance_id) except ProviderNotActive as pna: return inactive_provider(pna) except Exception as e: return failure_response(status.HTTP_409_CONFLICT, e.message) if not core_instance: instance_not_found(instance_id) try: tag = core_instance.tags.get(name__iexact=tag_slug) except CoreTag.DoesNotExist: return Response(['Tag does not exist'], status=status.HTTP_404_NOT_FOUND) serializer = TagSerializer(tag) return Response(serializer.data)
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.shared_with_user(user).get(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
def get(self, request, provider_uuid, identity_uuid, instance_id, tag_slug, *args, **kwargs): """ Return the credential information for this tag """ try: core_instance = get_core_instance(request, provider_uuid, identity_uuid, instance_id) except ProviderNotActive as pna: return inactive_provider(pna) except Exception as e: return failure_response( status.HTTP_409_CONFLICT, e.message) if not core_instance: instance_not_found(instance_id) try: tag = core_instance.tags.get(name__iexact=tag_slug) except CoreTag.DoesNotExist: return Response(['Tag does not exist'], status=status.HTTP_404_NOT_FOUND) serializer = TagSerializer(tag) return Response(serializer.data)
def get(self, request, provider_uuid, identity_uuid, machine_id): """ Details view for specific machine (Lookup using the given provider/identity) """ 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) # TODO: Need to determine that identity_uuid is ALLOWED to # see machine_id. if not covered by calling as the users driver.. esh_machine = esh_driver.get_machine(machine_id) core_machine = convert_esh_machine(esh_driver, esh_machine, provider_uuid, user) serialized_data = ProviderMachineSerializer( core_machine, request_user=request.user).data response = Response(serialized_data) return response
def keys_not_found(missing_keys): return failure_response( status.HTTP_400_BAD_REQUEST, 'Missing required POST datavariables : %s' % missing_keys)
def post(self, request, provider_uuid, identity_uuid): """ Creates a new volume and adds it to the DB """ user = request.user try: membership = IdentityMembership.objects.get( identity__uuid=identity_uuid, member__name=user.username) except: return failure_response( status.HTTP_409_CONFLICT, "Identity %s is invalid -OR- User %s does not have the appropriate IdentityMembership." % (identity_uuid, user)) try: 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 driver: return invalid_creds(provider_uuid, identity_uuid) data = request.data missing_keys = valid_volume_post_data(data) if missing_keys: return keys_not_found(missing_keys) # Pass arguments name = data.get('name') size = data.get('size') # Optional fields description = data.get('description') image_id = data.get('image') if image_id: image = driver.get_machine(image_id) image_size = image._connection.get_size(image._image) if int(size) > image_size + 4: return failure_response( status.HTTP_400_BAD_REQUEST, "Volumes created from images cannot exceed " "more than 4GB greater than the size of " "the image: %s GB" % image_size) else: image = None snapshot_id = data.get('snapshot') if snapshot_id: snapshot = driver._connection.ex_get_snapshot(image_id) else: snapshot = None try: success, esh_volume = create_esh_volume(driver, user.username, identity_uuid, name, size, description, snapshot=snapshot, image=image) except BaseHTTPError as http_error: if 'Requested volume or snapshot exceed' in http_error.message: return over_quota(http_error) return failure_response(status.HTTP_400_BAD_REQUEST, http_error.message) except OverQuotaError as oqe: return over_quota(oqe) except ConnectionFailure: return connection_failure(provider_uuid, identity_uuid) except LibcloudBadResponseError: return malformed_response(provider_uuid, identity_uuid) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) if not success: return failure_response( status.HTTP_500_INTERNAL_SERVER_ERROR, 'Volume creation failed. Contact support') # Volume creation succeeded core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) serialized_data = VolumeSerializer(core_volume, context={'request': request}).data return Response(serialized_data, status=status.HTTP_201_CREATED)
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) 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)) 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) 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: 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_uuid, identity_uuid, user) if not core_instance: logger.warn("Unable to find core instance %s." % (instance_id)) core_instance = CoreInstance.objects.filter( provider_alias=instance_id).first() 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)
def post(self, request, provider_uuid, identity_uuid, instance_id): """Authentication Required, Attempt a specific instance action, including necessary parameters. """ # Service-specific call to action action_params = request.data if not action_params.get('action', None): return failure_response( status.HTTP_400_BAD_REQUEST, 'POST request to /action require a BODY with \'action\'.') result_obj = None user = request.user identity = Identity.objects.get(uuid=identity_uuid) action = action_params['action'] try: if not can_use_instance(user, instance_id, leader_required=True): return member_action_forbidden(user.username, "Instance", instance_id) result_obj = run_instance_action(user, identity, instance_id, action, action_params) result_obj = _further_process_result(request, action, result_obj) api_response = { 'result': 'success', 'message': 'The requested action <%s> was run successfully' % (action_params['action'], ), 'object': result_obj, } response = Response(api_response, status=status.HTTP_200_OK) return response except (socket_error, ConnectionFailure): return connection_failure(provider_uuid, identity_uuid) except ProviderNotActive as pna: return inactive_provider(pna) except InstanceDoesNotExist as dne: return failure_response( status.HTTP_404_NOT_FOUND, 'Instance %s no longer exists' % (dne.message, )) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) except HypervisorCapacityError as hce: return over_capacity(hce) except OverQuotaError as oqe: return over_quota(oqe) except OverAllocationError as oae: return over_quota(oae) except SizeNotAvailable as snae: return size_not_available(snae) except (socket_error, ConnectionFailure): return connection_failure(provider_uuid, identity_uuid) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) except VolumeMountConflict as vmc: return mount_failed(vmc) except NotImplemented: return failure_response( status.HTTP_409_CONFLICT, "The requested action %s is not available on this provider." % action_params['action']) except ActionNotAllowed: return failure_response( status.HTTP_409_CONFLICT, "The requested action %s has been explicitly " "disabled on this provider." % action_params['action']) except Exception as exc: logger.exception("Exception occurred processing InstanceAction") message = exc.message if message.startswith('409 Conflict'): return failure_response(status.HTTP_409_CONFLICT, message) return failure_response( status.HTTP_403_FORBIDDEN, "The requested action %s encountered " "an irrecoverable exception: %s" % (action_params['action'], message))
def over_quota(quota_exception): return failure_response( status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, quota_exception.message)
def snapshot_not_found(snapshot_id): return failure_response( status.HTTP_404_NOT_FOUND, 'Snapshot %s does not exist' % snapshot_id)
def volume_not_found(volume_id): return failure_response( status.HTTP_404_NOT_FOUND, 'Volume %s does not exist' % volume_id)
def post(self, request, provider_uuid, identity_uuid): """ Updates DB values for volume """ user = request.user data = request.data missing_keys = valid_snapshot_post_data(data) if missing_keys: return keys_not_found(missing_keys) # Required size = data.get('size') volume_id = data.get('volume_id') display_name = data.get('display_name') # Optional description = data.get('description') metadata = data.get('metadata') snapshot_id = data.get('snapshot_id') # STEP 0 - Existence tests 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) try: esh_volume = esh_driver.get_volume(volume_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)) # TODO: Put quota tests at the TOP so we dont over-create resources! # STEP 1 - Reuse/Create snapshot if snapshot_id: snapshot = esh_driver._connection.get_snapshot(snapshot_id) if not snapshot: return failure_response( status.HTTP_400_BAD_REQUEST, "Snapshot %s not found. Process aborted." % snapshot_id) else: # Normal flow, create a snapshot from the volume if not esh_volume: return volume_not_found(volume_id) if esh_volume.extra['status'].lower() != 'available': return failure_response( status.HTTP_400_BAD_REQUEST, "Volume status must be 'available'. " "Did you detach the volume?") snapshot = esh_driver._connection.ex_create_snapshot( esh_volume, display_name, description) if not snapshot: return failure_response( status.HTTP_400_BAD_REQUEST, "Snapshot not created. Process aborted.") # STEP 2 - Create volume from snapshot try: success, esh_volume = create_esh_volume(esh_driver, identity_uuid, display_name, size, description, metadata, snapshot=snapshot) if not success: return failure_response( status.HTTP_500_INTERNAL_SERVER_ERROR, 'Volume creation failed. Contact support') # Volume creation succeeded core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) serialized_data = VolumeSerializer( core_volume, context={'request': request}).data return Response(serialized_data, status=status.HTTP_201_CREATED) except OverQuotaError as oqe: return over_quota(oqe) except ConnectionFailure: return connection_failure(provider_uuid, identity_uuid) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid)
def keys_not_found(missing_keys): return failure_response( status.HTTP_400_BAD_REQUEST, 'Missing data for variable(s): %s' % missing_keys)
def keys_not_found(missing_keys): return failure_response(status.HTTP_400_BAD_REQUEST, 'Missing data for variable(s): %s' % missing_keys)
def post(self, request, provider_uuid, identity_uuid): """ Creates a new volume and adds it to the DB """ user = request.user try: membership = IdentityMembership.objects.get( identity__uuid=identity_uuid, member__memberships__user=user) except: return failure_response( status.HTTP_409_CONFLICT, "Identity %s is invalid -OR- User %s does not have the appropriate IdentityMembership." % (identity_uuid, user)) try: 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 driver: return invalid_creds(provider_uuid, identity_uuid) data = request.data missing_keys = valid_volume_post_data(data) if missing_keys: return keys_not_found(missing_keys) # Pass arguments name = data.get('name') size = data.get('size') # Optional fields description = data.get('description') image_id = data.get('image') if image_id: image = driver.get_machine(image_id) image_size = image._connection.get_size(image._image) if int(size) > image_size + 4: return failure_response( status.HTTP_400_BAD_REQUEST, "Volumes created from images cannot exceed " "more than 4GB greater than the size of " "the image: %s GB" % image_size) else: image = None snapshot_id = data.get('snapshot') if snapshot_id: snapshot = driver._connection.ex_get_snapshot(image_id) else: snapshot = None try: success, esh_volume = create_esh_volume(driver, user.username, identity_uuid, name, size, description, snapshot=snapshot, image=image) except BaseHTTPError as http_error: if 'Requested volume or snapshot exceed' in http_error.message: return over_quota(http_error) return failure_response(status.HTTP_400_BAD_REQUEST, http_error.message) except OverQuotaError as oqe: return over_quota(oqe) except ConnectionFailure: return connection_failure(provider_uuid, identity_uuid) except LibcloudBadResponseError: return malformed_response(provider_uuid, identity_uuid) except LibcloudInvalidCredsError: return invalid_creds(provider_uuid, identity_uuid) if not success: return failure_response( status.HTTP_500_INTERNAL_SERVER_ERROR, 'Volume creation failed. Contact support') # Volume creation succeeded core_volume = convert_esh_volume(esh_volume, provider_uuid, identity_uuid, user) serialized_data = VolumeSerializer(core_volume, context={'request': request}).data return Response(serialized_data, status=status.HTTP_201_CREATED)
def post(self, request, provider_uuid, identity_uuid, format=None): """ Instance Class: Launches an instance based on the params Returns a single instance Parameters: machine_alias, size_alias, username TODO: Create a 'reverse' using the instance-id to pass the URL for the newly created instance I.e: url = "/provider/1/instance/1/i-12345678" """ data = request.data user = request.user # Check the data is valid missing_keys = valid_post_data(data) if missing_keys: return keys_not_found(missing_keys) identity = Identity.shared_with_user( user, is_leader=True).filter(uuid=identity_uuid).first() if not identity: failure_msg = "User %s does not have permission to POST with this identity. Promote user to leader or use a different Identity." % ( user, ) return failure_response(status.HTTP_403_FORBIDDEN, failure_msg) # Pass these as args size_alias = data.pop("size_alias") allocation_source_uuid = data.pop("allocation_source_uuid", None) machine_alias = data.pop("machine_alias") hypervisor_name = data.pop("hypervisor", None) if hypervisor_name: # Previous method passed this with 'None' but that fails now. # This check will only add the ex_ value if it is 'truthy'. data['ex_hypervisor_name'] = hypervisor_name deploy = data.pop("deploy", True) if type(deploy) in [str, unicode] and deploy.lower() == "false": deploy = False elif not isinstance(deploy, bool): deploy = True boot_scripts = data.pop("scripts", []) try: logger.debug(data) allocation_source = AllocationSource.objects.get( uuid=allocation_source_uuid) core_instance = launch_instance( user, identity_uuid, size_alias, machine_alias, deploy=deploy, allocation_source=allocation_source, **data) except UnderThresholdError as ute: return under_threshold(ute) except OverQuotaError as oqe: return over_quota(oqe) except OverAllocationError as oae: return over_quota(oae) except Unauthorized as auth_invalid: return invalid_creds(provider_uuid, identity_uuid) except SizeNotAvailable as snae: return size_not_available(snae) except SecurityGroupNotCreated: return connection_failure(provider_uuid, identity_uuid) 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)) serializer = InstanceSerializer(core_instance, context={"request": request}, data=data) if serializer.is_valid(): instance = serializer.save() if boot_scripts: _save_scripts_to_instance(instance, boot_scripts) instance.change_allocation_source(allocation_source) logger.info( "DEBUG- Instance launch completed - Returning instance %s (%s) to user %s" % (instance, instance.created_by_identity, request.user)) return Response(serializer.data, status=status.HTTP_201_CREATED) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)