From: Michael Tremer Date: Thu, 26 Jun 2025 16:00:41 +0000 (+0000) Subject: job: Implement some way to submit the job result X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=68c271c37e4a378990fe7aaaeaec87c0314bbfb8;p=pakfire.git job: Implement some way to submit the job result Signed-off-by: Michael Tremer --- diff --git a/src/pakfire/client.c b/src/pakfire/client.c index 362e2b5a..dab66c8f 100644 --- a/src/pakfire/client.c +++ b/src/pakfire/client.c @@ -1414,3 +1414,58 @@ ERROR: return r; } + +/* + This is called when a job has finished. +*/ +int pakfire_client_job_finished(struct pakfire_client* self, + const char* job_id, const char* logfile, char** packages) { + struct json_object* request = NULL; + struct pakfire_xfer* xfer = NULL; + int r; + + // Create a new request object + r = pakfire_json_new_object(&request); + if (r < 0) + goto ERROR; + + // XXX Add status + + // Add the logfile + if (logfile) { + r = pakfire_json_add_string(request, "logfile", logfile); + if (r < 0) + goto ERROR; + } + + // Add the packages + if (packages) { + r = pakfire_json_add_string_array(request, "packages", packages); + if (r < 0) + goto ERROR; + } + + // Create a new transfer + r = pakfire_client_xfer_create(&xfer, self, "/api/v1/jobs/%s", job_id); + if (r < 0) + goto ERROR; + + // Enable authentication + r = pakfire_client_xfer_auth(self, xfer); + if (r < 0) + goto ERROR; + + // Set the request body + r = pakfire_xfer_set_json_payload(xfer, request); + if (r < 0) + goto ERROR; + + // Enqueue the transfer + r = pakfire_httpclient_enqueue(self->httpclient, xfer); + +ERROR: + if (xfer) + pakfire_xfer_unref(xfer); + + return r; +} diff --git a/src/pakfire/client.h b/src/pakfire/client.h index 59b4bd19..b19346d2 100644 --- a/src/pakfire/client.h +++ b/src/pakfire/client.h @@ -110,4 +110,9 @@ int pakfire_client_create_repo(struct pakfire_client* client, int pakfire_client_delete_repo(struct pakfire_client* client, const char* distro, const char* name); +// Jobs + +int pakfire_client_job_finished(struct pakfire_client* self, + const char* job_id, const char* logfile, char** packages); + #endif /* PAKFIRE_CLIENT_H */ diff --git a/src/pakfire/job.c b/src/pakfire/job.c index b6a39e94..3514e3b0 100644 --- a/src/pakfire/job.c +++ b/src/pakfire/job.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +118,9 @@ struct pakfire_job { struct pakfire_job_uploads { char* logfile; char** packages; + + // Count how many uploads are running + int running; } uploads; }; @@ -276,42 +281,99 @@ static void pakfire_job_free(struct pakfire_job* job) { free(job); } -static int pakfire_job_xfer_create(struct pakfire_xfer** xfer, - struct pakfire_job* job, const char* url, ...) __attribute__((format(printf, 3, 4))); -static int pakfire_job_xfer_create(struct pakfire_xfer** xfer, - struct pakfire_job* job, const char* url, ...) { - struct pakfire_xfer* x = NULL; - va_list args; +static int pakfire_job_finished(struct pakfire_job* self) { int r; - va_start(args, url); - - // Create a new xfer - r = pakfire_xfer_create(&x, job->ctx, url, args); + // Submit the request + r = pakfire_client_job_finished(self->client, + self->id, self->uploads.logfile, self->uploads.packages); if (r < 0) - goto ERROR; + ERROR(self->ctx, "Failed to submit the finish request: %s\n", strerror(-r)); -#if 0 - // Set the base URL - r = pakfire_xfer_set_baseurl(x, pakfire_daemon_url(job->daemon)); - if (r < 0) - goto ERROR; -#endif + // Let the builder know this is finished + return pakfire_builder_job_finished(self->builder, self); +} + +static int pakfire_job_package_uploaded(struct pakfire_client* client, + pakfire_client_upload_status status, const char* path, const char* uuid, void* data) { + struct pakfire_job* self = data; + int r; - // Success - *xfer = pakfire_xfer_ref(x); + // Now we have one less uploads running + self->uploads.running--; -ERROR: - if (x) - pakfire_xfer_unref(x); - va_end(args); + switch (status) { + case PAKFIRE_CLIENT_UPLOAD_SUCCESSFUL: + // Store the ID of the upload + r = pakfire_strings_append(&self->uploads.packages, uuid); + if (r < 0) + return r; + break; - return r; + default: + ERROR(self->ctx, "Failed to upload %s: %s\n", path, strerror(status)); + + // XXX What do we do here? + + return status; + } + + // Don't do anything if there are any other uploads still running + if (self->uploads.running) + return 0; + + // Finish the job + return pakfire_job_finished(self); } static int pakfire_job_upload_packages(struct pakfire_job* self) { - return 0; // XXX TODO + FTSENT* entry = NULL; + FTS* fts = NULL; + int r = 0; + + char* paths[] = { + self->resultdir, NULL, + }; + + // Open the path + fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL); + if (!fts) { + ERROR(self->ctx, "Could not open %s: %m\n", self->resultdir); + r = -errno; + goto ERROR; + } + + // Scan for everything + for (;;) { + // Fetch the next entry + entry = fts_read(fts); + if (!entry) + break; + + // We only care about actual files + if (!(entry->fts_info & FTS_F)) + continue; + + // Skip anything that doesn't have the correct file extension + if (!pakfire_path_match("**.pfm", entry->fts_path)) + continue; + + // Upload the package + r = pakfire_client_upload(self->client, entry->fts_path, entry->fts_name, + pakfire_job_package_uploaded, self); + if (r < 0) + goto ERROR; + + // Now there is one more upload running + self->uploads.running++; + } + +ERROR: + if (fts) + fts_close(fts); + + return r; } /* @@ -344,98 +406,13 @@ static int pakfire_job_logfile_uploaded(struct pakfire_client* client, return pakfire_job_upload_packages(self); } -/* - Called when the job has finished with status as the error code. -*/ -static int pakfire_job_finished(struct pakfire_job* job, const siginfo_t* si) { - struct pakfire_xfer* xfer = NULL; - const char* filename = NULL; - const char* path = NULL; - int r; - - // Close the log file - r = pakfire_log_file_close(job->log.file); - if (r < 0) { - ERROR(job->ctx, "Could not close the log file: %s\n", strerror(-r)); - goto ERROR; - } - - // Fetch the filename of the log file - filename = pakfire_log_file_filename(job->log.file); - if (!filename) { - ERROR(job->ctx, "Log file has no filename\n"); - r = -EINVAL; - goto ERROR; - } - - // Fetch the path of the log file - path = pakfire_log_file_path(job->log.file); - if (!path) { - ERROR(job->ctx, "Log file has no path\n"); - r = -EINVAL; - goto ERROR; - } - - // Upload the log file - r = pakfire_client_upload(job->client, path, filename, pakfire_job_logfile_uploaded, job); - if (r < 0) { - ERROR(job->ctx, "Could not upload the log file: %s\n", strerror(-r)); - goto ERROR; - } - -#if 0 - // Create a new xfer - r = pakfire_job_xfer_create(&xfer, job, "/api/v1/jobs/%s/finished", job->id); - if (r < 0) - goto ERROR; - - // Enable authentication - r = pakfire_xfer_auth(xfer); - if (r < 0) - goto ERROR; - - // Has the job been successful? - r = pakfire_xfer_add_param(xfer, "success", "%s", (status == 0) ? "true" : "false"); - if (r < 0) - goto ERROR; - - // Logfile - if (logfile) { - r = pakfire_xfer_add_param(xfer, "logfile", "%s", logfile); - if (r) - goto ERROR; - } - - // Packages - if (job->uploads) { - for (char** upload = job->uploads; *upload; upload++) { - r = pakfire_xfer_add_param(xfer, "package", "%s", *upload); - if (r < 0) - goto ERROR; - } - } - - // Send the request - r = pakfire_xfer_run_api_request(xfer, NULL, NULL); - if (r < 0) - goto ERROR; -#endif - - // Let the builder know this is finished - r = pakfire_builder_job_finished(job->builder, job); - -ERROR: - if (xfer) - pakfire_xfer_unref(xfer); - - return r; -} - static int pakfire_job_result(struct pakfire_ctx* ctx, struct pakfire* pakfire, struct pakfire_build* build, struct pakfire_archive* archive, void* data) { - struct pakfire_job* job = data; + struct pakfire_job* self = data; struct pakfire_package* pkg = NULL; - char* uuid = NULL; + const char* filename = NULL; + const char* nevra = NULL; + char path[PATH_MAX]; int r; // Fetch package metadata @@ -444,45 +421,34 @@ static int pakfire_job_result(struct pakfire_ctx* ctx, struct pakfire* pakfire, goto ERROR; // Fetch NEVRA - const char* nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA); + nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA); if (!nevra) { r = -EINVAL; goto ERROR; } // Fetch filename - const char* filename = pakfire_package_get_filename(pkg); + filename = pakfire_package_get_filename(pkg); if (!filename) { r = -EINVAL; goto ERROR; } - // Fetch path - const char* path = pakfire_archive_get_path(archive); - if (!path) { - r = -EINVAL; + // Make the path + r = pakfire_path_format(path, "%s/%s", self->resultdir, filename); + if (r < 0) goto ERROR; - } -#if 0 - // Upload the file - r = pakfire_client_upload(job->client, path, filename, &uuid); + // Copy the archive to the result directory + r = pakfire_archive_copy(archive, path); if (r < 0) { - ERROR(job->ctx, "Could not upload %s: %s\n", nevra, strerror(-r)); + ERROR(self->ctx, "Failed to copy %s to %s: %s\n", nevra, path, strerror(-r)); goto ERROR; } -#endif - - // Store the ID of the upload - r = pakfire_strings_append(&job->uploads.packages, uuid); - if (r < 0) - goto ERROR; ERROR: if (pkg) pakfire_package_unref(pkg); - if (uuid) - free(uuid); return r; } @@ -492,6 +458,10 @@ ERROR: */ static int pakfire_job_exited(sd_event_source* s, const siginfo_t* si, void* data) { struct pakfire_job* job = data; + struct pakfire_xfer* xfer = NULL; + const char* filename = NULL; + const char* path = NULL; + int r; switch (si->si_code) { case CLD_EXITED: @@ -511,8 +481,41 @@ static int pakfire_job_exited(sd_event_source* s, const siginfo_t* si, void* dat break; } - // Signal that the job has finished - return pakfire_job_finished(job, si); + // Close the log file + r = pakfire_log_file_close(job->log.file); + if (r < 0) { + ERROR(job->ctx, "Could not close the log file: %s\n", strerror(-r)); + goto ERROR; + } + + // Fetch the filename of the log file + filename = pakfire_log_file_filename(job->log.file); + if (!filename) { + ERROR(job->ctx, "Log file has no filename\n"); + r = -EINVAL; + goto ERROR; + } + + // Fetch the path of the log file + path = pakfire_log_file_path(job->log.file); + if (!path) { + ERROR(job->ctx, "Log file has no path\n"); + r = -EINVAL; + goto ERROR; + } + + // Upload the log file + r = pakfire_client_upload(job->client, path, filename, pakfire_job_logfile_uploaded, job); + if (r < 0) { + ERROR(job->ctx, "Could not upload the log file: %s\n", strerror(-r)); + goto ERROR; + } + +ERROR: + if (xfer) + pakfire_xfer_unref(xfer); + + return r; } static int pakfire_job_send_log(struct pakfire_job* job, int priority, const char* line, size_t length) {