/* * Update pool record -- pull info from current POOL resource */ static bool update_pool(UAContext *ua) { POOL_DBR pr; int id; POOL *pool; POOLMEM *query; char ed1[50]; pool = get_pool_resource(ua); if (!pool) { return false; } memset(&pr, 0, sizeof(pr)); bstrncpy(pr.Name, pool->name(), sizeof(pr.Name)); if (!get_pool_dbr(ua, &pr)) { return false; } set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */ set_pooldbr_references(ua->jcr, ua->db, &pr, pool); id = db_update_pool_record(ua->jcr, ua->db, &pr); if (id <= 0) { ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"), id, db_strerror(ua->db)); } query = get_pool_memory(PM_MESSAGE); Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1)); db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST); free_pool_memory(query); ua->info_msg(_("Pool DB record updated from resource.\n")); return true; }
/* * Prune records from database * * prune files (from) client=xxx [pool=yyy] * prune jobs (from) client=xxx [pool=yyy] * prune volume=xxx * prune stats */ int prunecmd(UAContext *ua, const char *cmd) { CLIENTRES *client; POOLRES *pool; POOL_DBR pr; MEDIA_DBR mr; utime_t retention; int kw; static const char *keywords[] = { NT_("Files"), NT_("Jobs"), NT_("Volume"), NT_("Stats"), NULL}; if (!open_client_db(ua)) { return false; } /* First search args */ kw = find_arg_keyword(ua, keywords); if (kw < 0 || kw > 3) { /* no args, so ask user */ kw = do_keyword_prompt(ua, _("Choose item to prune"), keywords); } switch (kw) { case 0: /* prune files */ if (!(client = get_client_resource(ua))) { return false; } if (find_arg_with_value(ua, "pool") >= 0) { pool = get_pool_resource(ua); } else { pool = NULL; } /* Pool File Retention takes precedence over client File Retention */ if (pool && pool->FileRetention > 0) { if (!confirm_retention(ua, &pool->FileRetention, "File")) { return false; } } else if (!confirm_retention(ua, &client->FileRetention, "File")) { return false; } prune_files(ua, client, pool); return true; case 1: /* prune jobs */ if (!(client = get_client_resource(ua))) { return false; } if (find_arg_with_value(ua, "pool") >= 0) { pool = get_pool_resource(ua); } else { pool = NULL; } /* Pool Job Retention takes precedence over client Job Retention */ if (pool && pool->JobRetention > 0) { if (!confirm_retention(ua, &pool->JobRetention, "Job")) { return false; } } else if (!confirm_retention(ua, &client->JobRetention, "Job")) { return false; } /* ****FIXME**** allow user to select JobType */ prune_jobs(ua, client, pool, JT_BACKUP); return 1; case 2: /* prune volume */ if (!select_pool_and_media_dbr(ua, &pr, &mr)) { return false; } if (mr.Enabled == 2) { ua->error_msg(_("Cannot prune Volume \"%s\" because it is archived.\n"), mr.VolumeName); return false; } if (!confirm_retention(ua, &mr.VolRetention, "Volume")) { return false; } prune_volume(ua, &mr); return true; case 3: /* prune stats */ if (!director->stats_retention) { return false; } retention = director->stats_retention; if (!confirm_retention(ua, &retention, "Statistics")) { return false; } prune_stats(ua, retention); return true; default: break; } return true; }
/* * Implement Bareos bconsole command purge action * purge action= pool= volume= storage= devicetype= */ static int action_on_purge_cmd(UAContext *ua, const char *cmd) { bool allpools = false; int drive = -1; int nb = 0; uint32_t *results = NULL; const char *action = "all"; STORERES *store = NULL; POOLRES *pool = NULL; MEDIA_DBR mr; POOL_DBR pr; BSOCK *sd = NULL; memset(&pr, 0, sizeof(pr)); /* Look at arguments */ for (int i=1; i<ua->argc; i++) { if (bstrcasecmp(ua->argk[i], NT_("allpools"))) { allpools = true; } else if (bstrcasecmp(ua->argk[i], NT_("volume")) && is_name_valid(ua->argv[i], NULL)) { bstrncpy(mr.VolumeName, ua->argv[i], sizeof(mr.VolumeName)); } else if (bstrcasecmp(ua->argk[i], NT_("devicetype")) && ua->argv[i]) { bstrncpy(mr.MediaType, ua->argv[i], sizeof(mr.MediaType)); } else if (bstrcasecmp(ua->argk[i], NT_("drive")) && ua->argv[i]) { drive = atoi(ua->argv[i]); } else if (bstrcasecmp(ua->argk[i], NT_("action")) && is_name_valid(ua->argv[i], NULL)) { action=ua->argv[i]; } } /* Choose storage */ ua->jcr->res.wstore = store = get_storage_resource(ua, false); if (!store) { goto bail_out; } switch (store->Protocol) { case APT_NDMPV2: case APT_NDMPV3: case APT_NDMPV4: ua->warning_msg(_("Storage has non-native protocol.\n")); goto bail_out; default: break; } if (!open_db(ua)) { Dmsg0(100, "Can't open db\n"); goto bail_out; } if (!allpools) { /* force pool selection */ pool = get_pool_resource(ua); if (!pool) { Dmsg0(100, "Can't get pool resource\n"); goto bail_out; } bstrncpy(pr.Name, pool->name(), sizeof(pr.Name)); if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { Dmsg0(100, "Can't get pool record\n"); goto bail_out; } mr.PoolId = pr.PoolId; } /* * Look for all Purged volumes that can be recycled, are enabled and * have more the 10,000 bytes. */ mr.Recycle = 1; mr.Enabled = 1; mr.VolBytes = 10000; set_storageid_in_mr(store, &mr); bstrncpy(mr.VolStatus, "Purged", sizeof(mr.VolStatus)); if (!db_get_media_ids(ua->jcr, ua->db, &mr, &nb, &results)) { Dmsg0(100, "No results from db_get_media_ids\n"); goto bail_out; } if (!nb) { ua->send_msg(_("No Volumes found to perform %s action.\n"), action); goto bail_out; } if ((sd = open_sd_bsock(ua)) == NULL) { Dmsg0(100, "Can't open connection to sd\n"); goto bail_out; } /* * Loop over the candidate Volumes and actually truncate them */ for (int i=0; i < nb; i++) { mr.clear(); mr.MediaId = results[i]; if (db_get_media_record(ua->jcr, ua->db, &mr)) { /* TODO: ask for drive and change Pool */ if (bstrcasecmp("truncate", action) || bstrcasecmp("all", action)) { do_truncate_on_purge(ua, &mr, pr.Name, store->dev_name(), drive, sd); } } else { Dmsg1(0, "Can't find MediaId=%lld\n", (uint64_t) mr.MediaId); } } bail_out: close_db(ua); if (sd) { sd->signal(BNET_TERMINATE); sd->close(); ua->jcr->store_bsock = NULL; } ua->jcr->res.wstore = NULL; if (results) { free(results); } return 1; }
/* * Prune records from database * * prune files client=xxx [pool=yyy] * prune jobs client=xxx [pool=yyy] * prune volume=xxx * prune stats * prune directory=xxx [client=xxx] [recursive] */ int prune_cmd(UAContext *ua, const char *cmd) { CLIENTRES *client; POOLRES *pool; POOL_DBR pr; MEDIA_DBR mr; utime_t retention; int kw; static const char *keywords[] = { NT_("Files"), NT_("Jobs"), NT_("Volume"), NT_("Stats"), NT_("Directory"), NULL }; if (!open_client_db(ua, true)) { return false; } /* * First search args */ kw = find_arg_keyword(ua, keywords); if (kw < 0 || kw > 4) { /* * No args, so ask user */ kw = do_keyword_prompt(ua, _("Choose item to prune"), keywords); } switch (kw) { case 0: /* prune files */ if (!(client = get_client_resource(ua))) { return false; } if (find_arg_with_value(ua, NT_("pool")) >= 0) { pool = get_pool_resource(ua); } else { pool = NULL; } /* * Pool File Retention takes precedence over client File Retention */ if (pool && pool->FileRetention > 0) { if (!confirm_retention(ua, &pool->FileRetention, "File")) { return false; } } else if (!confirm_retention(ua, &client->FileRetention, "File")) { return false; } prune_files(ua, client, pool); return true; case 1: { /* prune jobs */ int i; char jobtype[MAX_NAME_LENGTH]; if (!(client = get_client_resource(ua))) { return false; } if (find_arg_with_value(ua, NT_("pool")) >= 0) { pool = get_pool_resource(ua); } else { pool = NULL; } /* * Ask what jobtype to prune. */ if ((i = find_arg_with_value(ua, NT_("jobtype"))) >= 0) { bstrncpy(jobtype, ua->argv[i], sizeof(jobtype)); } else { start_prompt(ua, _("Jobtype to prune:\n")); for (i = 0; jobtypes[i].type_name; i++) { add_prompt(ua, jobtypes[i].type_name); } if (do_prompt(ua, _("JobType"), _("Select Job Type"), jobtype, sizeof(jobtype)) < 0) { return true; } } for (i = 0; jobtypes[i].type_name; i++) { if (bstrcasecmp(jobtypes[i].type_name, jobtype)) { break; } } if (!jobtypes[i].type_name) { ua->warning_msg(_("Illegal jobtype %s.\n"), jobtype); return false; } /* * Pool Job Retention takes precedence over client Job Retention */ if (pool && pool->JobRetention > 0) { if (!confirm_retention(ua, &pool->JobRetention, "Job")) { return false; } } else if (!confirm_retention(ua, &client->JobRetention, "Job")) { return false; } if (jobtypes[i].type_name) { return prune_jobs(ua, client, pool, jobtypes[i].job_type); } return false; } case 2: /* prune volume */ if (!select_pool_and_media_dbr(ua, &pr, &mr)) { return false; } if (mr.Enabled == 2) { ua->error_msg(_("Cannot prune Volume \"%s\" because it is archived.\n"), mr.VolumeName); return false; } if (!confirm_retention(ua, &mr.VolRetention, "Volume")) { return false; } return prune_volume(ua, &mr); case 3: /* prune stats */ if (!me->stats_retention) { return false; } retention = me->stats_retention; if (!confirm_retention(ua, &retention, "Statistics")) { return false; } return prune_stats(ua, retention); case 4: /* prune directory */ if (find_arg_with_value(ua, NT_("client")) >= 0) { if (!(client = get_client_resource(ua))) { return false; } } else { client = NULL; } return prune_directory(ua, client); default: break; } return true; }