def create(self): """ Create this object in fl33t :returns: :py:class:`self`, on success or False, on failure :raises UnprivilegedToken: if the session token does not have enough privilege to perform this action :raises Fl33tApiException: if there was a 5xx error returned by fl33t :raises Fl33tClientException: if the model was instantiated without a :py:class:`fl33t.Fl33tClient` """ if not self._client: raise Fl33tClientException() class_name = self.__class__.__name__.lower() result = self._client.post(self.base_url, data=self) # 409 is a duplicate ID error for devices. For other models, this # error shouldn't occur because all other ID's are generated by fl33t if result.status_code == 409: raise Fl33tApiException(result.text) if class_name not in result.json(): self.logger.exception('Could not create {}'.format(class_name)) return False data = result.json()[class_name] for key in data.keys(): setattr(self, key, data[key]) return self
def create(self): """ Create this device in fl33t :returns: :py:class:`self` on success, or False on failure :raises DuplicateDeviceIdError: if the device ID already exists :raises UnprivilegedToken: if the session token does not have enough privilege to perform this action :raises Fl33tApiException: if there was a 5xx error returned by fl33t :raises Fl33tClientException: if the model was instantiated without a :py:class:`fl33t.Fl33tClient` """ if not self._client: raise Fl33tClientException() result = self._client.post(self.base_url, data=self) if result.status_code == 409: raise DuplicateDeviceIdError(self.device_id) if 'device' not in result.json(): self.logger.exception('Could not create device') return False data = result.json()['device'] for key in data.keys(): setattr(self, key, data[key]) return self
def delete(self): """ Delete this object from a fl33t :returns: True on success, or False on failure :raises UnprivilegedToken: if the session token does not have enough privilege to perform this action :raises Fl33tApiException: if there was a 5xx error returned by fl33t :raises Fl33tClientException: if the model was instantiated without a :py:class:`fl33t.Fl33tClient` """ if not self._client: raise Fl33tClientException() result = self._client.delete(self.self_url) if result.status_code in (400, 404): raise self._invalid_id(self.id) if result.status_code != 204: self.logger.warning('Received {}: {}'.format( result.status_code, result.text)) return False return True
def create(self): """ Create this build record in fl33t and upload the new build file :returns: :py:class:`self` on success, or False on failure :raises UnprivilegedToken: if the session token does not have enough privilege to perform this action :raises Fl33tApiException: if there was a 5xx error returned by fl33t :raises Fl33tClientException: if the model was instantiated without a :py:class:`fl33t.Fl33tClient` """ if not self._client: raise Fl33tClientException() result = self._client.post(self.base_url, data=self) if 'build' not in result.json(): self.logger.exception('Could not create build for: {}'.format( self.version)) return False data = result.json()['build'] for key in data.keys(): if key in ['filename', 'size']: # Allowing the filename to be overridden will break the upload # and size is unknown to the fl33t API at this point, so leave # it as was passed in to (or determined by) the object continue setattr(self, key, data[key]) if not self.upload_url: self.logger.exception( 'Build creation worked, but no upload_url was' ' provided by fl33t for build: {}'.format(self.version)) return self # The Content-Disposition header is what sets the filename in fl33t headers = { 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="{}"'.format(self.filename) } with open(self.fullpath, 'rb') as build_file: # Must use requests directly as we do not want the normal fl33t # API headers to be added to the upload request. The upload_url is # a pre-signed URL and as such has all authentication built-in. response = requests.put(self.upload_url, data=build_file.read(), headers=headers) # Any non-200 status is an error with the upload. if not response or response.status_code != 200: self.logger.exception('Failed to upload build file: {}'.format( self.version)) return False return self
def upgrade_available(self, installed_build_id=None): """ Returns the available firmware update, if there is one :param installed_build_id: The currently installed build ID, if known :type installed_build_id: str or None :returns: :py:class:`fl33t.models.Build`, if upgrade available or False, if none :raises UnprivilegedToken: if the session token does not have enough privilege to perform this action :raises Fl33tApiException: if there was a 5xx error returned by fl33t :raises Fl33tClientException: if the model was instantiated without a :py:class:`fl33t.Fl33tClient` """ if not self._client: raise Fl33tClientException() if not installed_build_id and self.build_id: installed_build_id = self.build_id return self._client.has_upgrade_available( self.device_id, currently_installed_id=installed_build_id)