X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fua_cmds.c;h=063127981d3599e7861495c3d78c909d63e3a233;hb=b9ac1b6c82fd69ecf139edce98585a889906db8b;hp=48e1d49a82b1097916b07e82e8eacdfde87d3c32;hpb=7e4f21a4f818abe5ac5a5eef0552f56e0be9e235;p=bacula%2Fbacula diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 48e1d49a82..063127981d 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -8,7 +8,7 @@ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2000-2004 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -75,10 +75,12 @@ static int update_volume(UAContext *ua); static int update_pool(UAContext *ua); static int delete_volume(UAContext *ua); static int delete_pool(UAContext *ua); +static int delete_job(UAContext *ua); static int mount_cmd(UAContext *ua, char *cmd); static int release_cmd(UAContext *ua, char *cmd); static int update_cmd(UAContext *ua, char *cmd); static int wait_cmd(UAContext *ua, char *cmd); +static int setip_cmd(UAContext *ua, char *cmd); int quit_cmd(UAContext *ua, char *cmd); @@ -94,23 +96,24 @@ static struct cmdstruct commands[] = { { N_("estimate"), estimate_cmd, _("performs FileSet estimate, listing gives full listing")}, { N_("exit"), quit_cmd, _("exit = quit")}, { N_("help"), help_cmd, _("print this command")}, + { N_("list"), list_cmd, _("list [pools | jobs | jobtotals | media | files jobid=]; from catalog")}, { N_("label"), label_cmd, _("label a tape")}, - { N_("list"), list_cmd, _("list [pools | jobs | jobtotals | media | files job=]; from catalog")}, { N_("llist"), llist_cmd, _("full or long list like list command")}, { N_("messages"), messagescmd, _("messages")}, { N_("mount"), mount_cmd, _("mount ")}, { N_("prune"), prunecmd, _("prune expired records from catalog")}, { N_("purge"), purgecmd, _("purge records from catalog")}, - { N_("query"), querycmd, _("query catalog")}, { N_("quit"), quit_cmd, _("quit")}, + { N_("query"), querycmd, _("query catalog")}, + { N_("restore"), restore_cmd, _("restore files")}, { N_("relabel"), relabel_cmd, _("relabel a tape")}, { N_("release"), release_cmd, _("release ")}, - { N_("restore"), restore_cmd, _("restore files")}, { N_("run"), run_cmd, _("run ")}, + { N_("status"), status_cmd, _("status [storage | client]=")}, { N_("setdebug"), setdebug_cmd, _("sets debug level")}, + { N_("setip"), setip_cmd, _("sets new client address -- if authorized")}, { N_("show"), show_cmd, _("show (resource records) [jobs | pools | ... | all]")}, { N_("sqlquery"), sqlquerycmd, _("use SQL to query catalog")}, - { N_("status"), status_cmd, _("status [storage | client]=")}, { N_("time"), time_cmd, _("print current time")}, { N_("unmount"), unmount_cmd, _("unmount ")}, { N_("update"), update_cmd, _("update Volume or Pool")}, @@ -128,12 +131,11 @@ int do_a_command(UAContext *ua, char *cmd) { unsigned int i; int len, stat; - int found; + bool found = false; - found = 0; stat = 1; - Dmsg1(120, "Command: %s\n", ua->UA_sock->msg); + Dmsg1(200, "Command: %s\n", ua->UA_sock->msg); if (ua->argc == 0) { return 1; } @@ -141,15 +143,16 @@ int do_a_command(UAContext *ua, char *cmd) len = strlen(ua->argk[0]); for (i=0; iargk[0], _(commands[i].key), len) == 0) { + if (!acl_access_ok(ua, Command_ACL, ua->argk[0], len)) { + break; + } stat = (*commands[i].func)(ua, cmd); /* go execute command */ - found = 1; + found = true; break; } } if (!found) { - pm_strcat(&ua->UA_sock->msg, _(": is an illegal command\n")); - ua->UA_sock->msglen = strlen(ua->UA_sock->msg); - bnet_send(ua->UA_sock); + bnet_fsend(ua->UA_sock, _("%s: is an illegal command.\n"), ua->argk[0]); } return stat; } @@ -183,7 +186,7 @@ static int add_cmd(UAContext *ua, char *cmd) int first_id = 0; char name[MAX_NAME_LENGTH]; STORE *store; - int slot = 0; + int Slot = 0, InChanger = 0; bsendmsg(ua, _( "You probably don't want to be using this command since it\n" @@ -286,13 +289,18 @@ getVolName: if (!get_pint(ua, _("Enter slot (0 for none): "))) { return 1; } - slot = ua->pint32_val; + Slot = ua->pint32_val; + if (!get_yesno(ua, _("InChanger? yes/no: "))) { + return 1; + } + InChanger = ua->pint32_val; } set_pool_dbr_defaults_in_media_dbr(&mr, &pr); for (i=startnum; i < num+startnum; i++) { bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), name, i); - mr.Slot = slot++; + mr.Slot = Slot++; + mr.InChanger = InChanger; Dmsg1(200, "Create Volume %s\n", mr.VolumeName); if (!db_create_media_record(ua->jcr, ua->db, &mr)) { bsendmsg(ua, db_strerror(ua->db)); @@ -342,9 +350,8 @@ int automount_cmd(UAContext *ua, char *cmd) */ static int cancel_cmd(UAContext *ua, char *cmd) { - int i; + int i, ret; int njobs = 0; - BSOCK *sd, *fd; JCR *jcr = NULL; char JobName[MAX_NAME_LENGTH]; @@ -354,11 +361,13 @@ static int cancel_cmd(UAContext *ua, char *cmd) for (i=1; iargc; i++) { if (strcasecmp(ua->argk[i], _("jobid")) == 0) { + uint32_t JobId; if (!ua->argv[i]) { break; } - if (!(jcr=get_jcr_by_id(atoi(ua->argv[i])))) { - bsendmsg(ua, _("JobId %d is not running.\n"), atoi(ua->argv[i])); + JobId = str_to_int64(ua->argv[i]); + if (!(jcr=get_jcr_by_id(JobId))) { + bsendmsg(ua, _("JobId %d is not running.\n"), JobId); return 1; } break; @@ -379,13 +388,13 @@ static int cancel_cmd(UAContext *ua, char *cmd) if (!jcr) { /* Count Jobs running */ lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) { + foreach_jcr(jcr) { if (jcr->JobId == 0) { /* this is us */ free_locked_jcr(jcr); - njobs--; continue; } free_locked_jcr(jcr); + njobs++; } unlock_jcr_chain(); @@ -395,7 +404,7 @@ static int cancel_cmd(UAContext *ua, char *cmd) } start_prompt(ua, _("Select Job:\n")); lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + foreach_jcr(jcr) { if (jcr->JobId == 0) { /* this is us */ free_locked_jcr(jcr); continue; @@ -413,72 +422,18 @@ static int cancel_cmd(UAContext *ua, char *cmd) return 1; } } + /* NOTE! This increments the ref_count */ jcr = get_jcr_by_full_name(JobName); if (!jcr) { bsendmsg(ua, _("Job %s not found.\n"), JobName); return 1; } } - - switch (jcr->JobStatus) { - case JS_Created: - case JS_WaitJobRes: - case JS_WaitClientRes: - case JS_WaitStoreRes: - case JS_WaitPriority: - case JS_WaitMaxJobs: - case JS_WaitStartTime: - set_jcr_job_status(jcr, JS_Canceled); - bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"), - jcr->JobId, jcr->Job); - jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */ - free_jcr(jcr); /* this decrements the use count only */ - return 1; - - default: - set_jcr_job_status(jcr, JS_Canceled); - - /* Cancel File daemon */ - if (jcr->file_bsock) { - ua->jcr->client = jcr->client; - if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to File daemon.\n")); - free_jcr(jcr); - return 1; - } - Dmsg0(200, "Connected to file daemon\n"); - fd = ua->jcr->file_bsock; - bnet_fsend(fd, "cancel Job=%s\n", jcr->Job); - while (bnet_recv(fd) >= 0) { - bsendmsg(ua, "%s", fd->msg); - } - bnet_sig(fd, BNET_TERMINATE); - bnet_close(fd); - ua->jcr->file_bsock = NULL; - } - /* Cancel Storage daemon */ - if (jcr->store_bsock) { - ua->jcr->store = jcr->store; - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); - free_jcr(jcr); - return 1; - } - Dmsg0(200, "Connected to storage daemon\n"); - sd = ua->jcr->store_bsock; - bnet_fsend(sd, "cancel Job=%s\n", jcr->Job); - while (bnet_recv(sd) >= 0) { - bsendmsg(ua, "%s", sd->msg); - } - bnet_sig(sd, BNET_TERMINATE); - bnet_close(sd); - ua->jcr->store_bsock = NULL; - } - } + ret = cancel_job(ua, jcr); free_jcr(jcr); - return 1; + return ret; } /* @@ -575,8 +530,8 @@ static int create_cmd(UAContext *ua, char *cmd) switch (create_pool(ua->jcr, ua->db, pool, POOL_OP_CREATE)) { case 0: - bsendmsg(ua, _("Error: Pool %s already exists.\n\ -Use update to change it.\n"), pool->hdr.name); + bsendmsg(ua, _("Error: Pool %s already exists.\n" + "Use update to change it.\n"), pool->hdr.name); break; case -1: @@ -591,6 +546,34 @@ Use update to change it.\n"), pool->hdr.name); } +/* + * Set a new address in a Client resource. We do this only + * if the Console name is the same as the Client name + * and the Console can access the client. + */ +static int setip_cmd(UAContext *ua, char *cmd) +{ + CLIENT *client; + if (!ua->cons || !acl_access_ok(ua, Client_ACL, ua->cons->hdr.name)) { + bsendmsg(ua, _("Illegal command from this console.\n")); + return 1; + } + client = (CLIENT *)GetResWithName(R_CLIENT, ua->cons->hdr.name); + + if (!client) { + bsendmsg(ua, _("Client \"%s\" not found.\n"), ua->cons->hdr.name); + return 1; + } + LockRes(); + if (client->address) { + free(client->address); + } + client->address = bstrdup(inet_ntoa(ua->UA_sock->client_addr.sin_addr)); + bsendmsg(ua, _("Client \"%s\" address set to %s\n"), + client->hdr.name, client->address); + UnlockRes(); + return 1; +} /* @@ -793,7 +776,7 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) if (!db_sql_query(ua->db, query, NULL, NULL)) { bsendmsg(ua, "%s", db_strerror(ua->db)); } else { - bsendmsg(ua, _("New recycle flag is: %s\n"), + bsendmsg(ua, _("New Recycle flag is: %s\n"), mr->Recycle==1?_("yes"):_("no")); } free_pool_memory(query); @@ -803,20 +786,22 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) static void update_volpool(UAContext *ua, char *val, MEDIA_DBR *mr) { POOL_DBR pr; - POOLMEM *query; + memset(&pr, 0, sizeof(pr)); bstrncpy(pr.Name, val, sizeof(pr.Name)); if (!get_pool_dbr(ua, &pr)) { return; } - query = get_pool_memory(PM_MESSAGE); - Mmsg(&query, "UPDATE Media SET PoolId=%u WHERE MediaId=%u", pr.PoolId, mr->MediaId); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { + mr->PoolId = pr.PoolId; /* set new PoolId */ + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, mr)) { + bsendmsg(ua, _("Error updating media record Pool: ERR=%s"), db_strerror(ua->db)); + } else { bsendmsg(ua, _("New Pool is: %s\n"), pr.Name); } - free_pool_memory(query); } /* @@ -892,6 +877,7 @@ static int update_volume(UAContext *ua) add_prompt(ua, _("Maximum Volume Bytes")); add_prompt(ua, _("Recycle Flag")); add_prompt(ua, _("Slot")); + add_prompt(ua, _("InChanger Flag")); add_prompt(ua, _("Volume Files")); add_prompt(ua, _("Pool")); add_prompt(ua, _("Done")); @@ -968,7 +954,7 @@ static int update_volume(UAContext *ua) break; case 7: /* Slot */ - int slot; + int Slot; memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; @@ -980,24 +966,43 @@ static int update_volume(UAContext *ua) if (!get_pint(ua, _("Enter new Slot: "))) { return 0; } - slot = ua->pint32_val; - if (pr.MaxVols > 0 && slot > (int)pr.MaxVols) { + Slot = ua->pint32_val; + if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) { bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"), pr.MaxVols); break; } - query = get_pool_memory(PM_MESSAGE); - Mmsg(&query, "UPDATE Media SET Slot=%d WHERE MediaId=%u", - slot, mr.MediaId); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + mr.Slot = Slot; + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); } else { - bsendmsg(ua, "New Slot is: %d\n", slot); + bsendmsg(ua, _("New Slot is: %s\n"), mr.Slot); } - free_pool_memory(query); break; - case 8: /* Volume Files */ + case 8: /* InChanger */ + bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger); + if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) { + return 0; + } + mr.InChanger = ua->pint32_val; + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger); + } + break; + + + case 9: /* Volume Files */ int32_t VolFiles; bsendmsg(ua, _("Warning changing Volume Files can result\n" "in loss of data on your Volume\n\n")); @@ -1023,7 +1028,7 @@ static int update_volume(UAContext *ua) free_pool_memory(query); break; - case 9: /* Volume's Pool */ + case 10: /* Volume's Pool */ memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { @@ -1036,6 +1041,7 @@ static int update_volume(UAContext *ua) } update_volpool(ua, ua->cmd, &mr); return 1; + default: /* Done or error */ bsendmsg(ua, "Selection done.\n"); return 1; @@ -1244,7 +1250,8 @@ static int setdebug_cmd(UAContext *ua, char *cmd) debug_level = level; return 1; } - if (strcasecmp(ua->argk[i], _("client")) == 0) { + if (strcasecmp(ua->argk[i], _("client")) == 0 || + strcasecmp(ua->argk[i], _("fd")) == 0) { client = NULL; if (ua->argv[i]) { client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]); @@ -1261,7 +1268,8 @@ static int setdebug_cmd(UAContext *ua, char *cmd) } if (strcasecmp(ua->argk[i], _("store")) == 0 || - strcasecmp(ua->argk[i], _("storage")) == 0) { + strcasecmp(ua->argk[i], _("storage")) == 0 || + strcasecmp(ua->argk[i], _("sd")) == 0) { store = NULL; if (ua->argv[i]) { store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]); @@ -1342,7 +1350,8 @@ static int estimate_cmd(UAContext *ua, char *cmd) char since[MAXSTRING]; for (int i=1; iargc; i++) { - if (strcasecmp(ua->argk[i], _("client")) == 0) { + if (strcasecmp(ua->argk[i], _("client")) == 0 || + strcasecmp(ua->argk[i], _("fd")) == 0) { if (ua->argv[i]) { client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]); continue; @@ -1451,15 +1460,13 @@ static int delete_cmd(UAContext *ua, char *cmd) static char *keywords[] = { N_("volume"), N_("pool"), + N_("job"), NULL}; if (!open_db(ua)) { return 1; } - bsendmsg(ua, _( -"In general it is not a good idea to delete either a\n" -"Pool or a Volume since they may contain data.\n\n")); switch (find_arg_keyword(ua, keywords)) { case 0: @@ -1468,9 +1475,17 @@ static int delete_cmd(UAContext *ua, char *cmd) case 1: delete_pool(ua); return 1; + case 2: + delete_job(ua); + return 1; default: break; } + + bsendmsg(ua, _( +"In general it is not a good idea to delete either a\n" +"Pool or a Volume since they may contain data.\n\n")); + switch (do_keyword_prompt(ua, _("Choose catalog item to delete"), keywords)) { case 0: delete_volume(ua); @@ -1478,6 +1493,9 @@ static int delete_cmd(UAContext *ua, char *cmd) case 1: delete_pool(ua); break; + case 2: + delete_job(ua); + return 1; default: bsendmsg(ua, _("Nothing done.\n")); break; @@ -1485,6 +1503,30 @@ static int delete_cmd(UAContext *ua, char *cmd) return 1; } +static int delete_job(UAContext *ua) +{ + POOLMEM *query = get_pool_memory(PM_MESSAGE); + JobId_t JobId; + + int i = find_arg_with_value(ua, "jobid"); + if (i >= 0) { + JobId = str_to_int64(ua->argv[i]); + } else if (!get_pint(ua, _("Enter JobId to delete: "))) { + return 0; + } else { + JobId = ua->pint32_val; + } + Mmsg(&query, "DELETE FROM Job WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM File WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + free_pool_memory(query); + bsendmsg(ua, _("Job %u and associated records deleted from the catalog.\n"), JobId); + return 1; +} + /* * Delete media records from database -- dangerous */ @@ -1632,13 +1674,14 @@ int quit_cmd(UAContext *ua, char *cmd) */ int wait_cmd(UAContext *ua, char *cmd) { + JCR *jcr; bmicrosleep(0, 200000); /* let job actually start */ - for (int running=1; running; ) { - running = 0; + for (bool running=true; running; ) { + running = false; lock_jcr_chain(); - for (JCR *jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + foreach_jcr(jcr) { if (jcr->JobId != 0) { - running = 1; + running = true; free_locked_jcr(jcr); break; } @@ -1657,12 +1700,11 @@ static int help_cmd(UAContext *ua, char *cmd) { unsigned int i; -/* usage(); */ bsendmsg(ua, _(" Command Description\n ======= ===========\n")); for (i=0; idb) { db_close_database(ua->jcr, ua->db); + ua->db = NULL; + if (ua->jcr) { + ua->jcr->db = NULL; + } } - ua->db = NULL; }