3 * Bacula Director -- User Agent Commands
5 * Kern Sibbald, September MM
9 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public
22 License along with this program; if not, write to the Free
23 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
32 /* Imported subroutines */
33 extern void run_job(JCR *jcr);
35 /* Imported variables */
36 extern struct s_jl joblevels[];
39 extern struct s_res resources[];
40 extern int console_msg_pending;
42 extern char my_name[];
44 /* Imported functions */
45 extern int statuscmd(UAContext *ua, char *cmd);
46 extern int listcmd(UAContext *ua, char *cmd);
47 extern int showcmd(UAContext *ua, char *cmd);
48 extern int messagescmd(UAContext *ua, char *cmd);
49 extern int autodisplaycmd(UAContext *ua, char *cmd);
50 extern int sqlquerycmd(UAContext *ua, char *cmd);
51 extern int querycmd(UAContext *ua, char *cmd);
52 extern int runcmd(UAContext *ua, char *cmd);
53 extern int retentioncmd(UAContext *ua, char *cmd);
55 /* Forward referenced functions */
56 static int addcmd(UAContext *ua, char *cmd), createcmd(UAContext *ua, char *cmd), cancelcmd(UAContext *ua, char *cmd);
57 static int setdebugcmd(UAContext *ua, char *cmd);
58 static int helpcmd(UAContext *ua, char *cmd);
59 static int deletecmd(UAContext *ua, char *cmd);
60 static int usecmd(UAContext *ua, char *cmd), unmountcmd(UAContext *ua, char *cmd);
61 static int labelcmd(UAContext *ua, char *cmd), mountcmd(UAContext *ua, char *cmd), updatecmd(UAContext *ua, char *cmd);
62 static int versioncmd(UAContext *ua, char *cmd), automountcmd(UAContext *ua, char *cmd);
63 static int update_media(UAContext *ua);
64 static int update_pool(UAContext *ua);
65 static int delete_media(UAContext *ua);
66 static int delete_pool(UAContext *ua);
68 int quitcmd(UAContext *ua, char *cmd);
71 struct cmdstruct { char *key; int (*func)(UAContext *ua, char *cmd); char *help; };
72 static struct cmdstruct commands[] = {
73 { N_("add"), addcmd, _("add media to a pool")},
74 { N_("autodisplay"), autodisplaycmd, _("autodisplay [on/off] -- console messages")},
75 { N_("automount"), automountcmd, _("automount [on/off] -- after label")},
76 { N_("cancel"), cancelcmd, _("cancel job=nnn -- cancel a job")},
77 { N_("create"), createcmd, _("create DB Pool from resource")},
78 { N_("delete"), deletecmd, _("delete [pool=<pool-name> | media volume=<volume-name>]")},
79 { N_("help"), helpcmd, _("print this command")},
80 { N_("label"), labelcmd, _("label a tape")},
81 { N_("list"), listcmd, _("list [pools | jobs | jobtotals | media <pool> | files job=<nn>]; from catalog")},
82 { N_("messages"), messagescmd, _("messages")},
83 { N_("mount"), mountcmd, _("mount <storage-name>")},
84 { N_("retention"), retentioncmd, _("retention")},
85 { N_("run"), runcmd, _("run <job-name>")},
86 { N_("setdebug"), setdebugcmd, _("sets debug level")},
87 { N_("show"), showcmd, _("show (resource records) [jobs | pools | ... | all]")},
88 { N_("sqlquery"), sqlquerycmd, _("use SQL to query catalog")},
89 { N_("status"), statuscmd, _("status [storage | client]=<name>")},
90 { N_("unmount"), unmountcmd, _("unmount <storage-name>")},
91 { N_("update"), updatecmd, _("update DB Pool from resource")},
92 { N_("use"), usecmd, _("use catalog xxx")},
93 { N_("version"), versioncmd, _("print Director version")},
94 { N_("quit"), quitcmd, _("quit")},
95 { N_("query"), querycmd, _("query catalog")},
96 { N_("exit"), quitcmd, _("exit = quit")},
98 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
101 * Execute a command from the UA
103 int do_a_command(UAContext *ua, char *cmd)
112 Dmsg1(20, "Command: %s\n", ua->UA_sock->msg);
117 len = strlen(ua->argk[0]);
118 for (i=0; i<comsize; i++) /* search for command */
119 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
120 stat = (*commands[i].func)(ua, cmd); /* go execute command */
125 strcat(ua->UA_sock->msg, _(": is an illegal command\n"));
126 ua->UA_sock->msglen = strlen(ua->UA_sock->msg);
127 bnet_send(ua->UA_sock);
134 * Add Volumes to an existing Pool
137 static int addcmd(UAContext *ua, char *cmd)
141 int num, i, max, startnum;
143 char name[MAX_NAME_LENGTH];
146 "You probably don't want to be using this command since it\n"
147 "creates database records without labeling the Volumes.\n"
148 "You probably want to use the label command.\n\n"));
154 memset(&pr, 0, sizeof(pr));
155 memset(&mr, 0, sizeof(mr));
157 if (!get_pool_dbr(ua, &pr)) {
161 Dmsg4(20, "id=%d Num=%d Max=%d type=%s\n", pr.PoolId, pr.NumVols,
162 pr.MaxVols, pr.PoolType);
164 while (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) {
165 bsendmsg(ua, _("Pool already has maximum volumes = %d\n"), pr.MaxVols);
167 if (!get_cmd(ua, _("Enter new maximum (zero for unlimited): "))) {
170 pr.MaxVols = atoi(ua->cmd);
171 if (pr.MaxVols < 0) {
172 bsendmsg(ua, _("Max vols must be zero or greater.\n"));
179 if (!get_media_type(ua, mr.MediaType)) {
183 if (pr.MaxVols == 0) {
186 max = pr.MaxVols - pr.NumVols;
190 sprintf(buf, _("Enter number of Volumes to create. 0=>fixed name. Max=%d: "), max);
191 if (!get_cmd(ua, buf)) {
195 if (num < 0 || num > max) {
196 bsendmsg(ua, _("The number must be between 0 and %d\n"), max);
203 if (!get_cmd(ua, _("Enter Volume name: "))) {
207 if (!get_cmd(ua, _("Enter base volume name: "))) {
211 if (strchr(ua->cmd, '|')) {
212 bsendmsg(ua, _("Illegal character | in a volume name.\n"));
215 if (strlen(ua->cmd) >= MAX_NAME_LENGTH-10) {
216 bsendmsg(ua, _("Volume name too long.\n"));
220 strcpy(name, ua->cmd);
222 strcat(name, "%04d");
225 if (!get_cmd(ua, _("Enter the starting number: "))) {
228 startnum = atoi(ua->cmd);
230 bsendmsg(ua, _("Start number must be greater than zero.\n"));
240 mr.PoolId = pr.PoolId;
241 strcpy(mr.VolStatus, "Append");
242 strcpy(mr.Recycle, "No");
243 for (i=startnum; i < num+startnum; i++) {
244 sprintf(mr.VolumeName, name, i);
245 Dmsg1(200, "Create Volume %s\n", mr.VolumeName);
246 if (!db_create_media_record(ua->db, &mr)) {
247 bsendmsg(ua, db_strerror(ua->db));
251 first_id = mr.PoolId;
255 Dmsg0(200, "Update pool record.\n");
256 if (db_update_pool_record(ua->db, &pr) != 1) {
257 bsendmsg(ua, db_strerror(ua->db));
260 bsendmsg(ua, _("%d Volumes created in pool %s\n"), num, pr.Name);
266 * Turn auto mount on/off
271 int automountcmd(UAContext *ua, char *cmd)
276 if (!get_cmd(ua, _("Turn on or off? "))) {
284 ua->automount = (strcasecmp(onoff, _("off")) == 0) ? 0 : 1;
292 static int cancelcmd(UAContext *ua, char *cmd)
298 char JobName[MAX_NAME_LENGTH];
304 for (i=1; i<ua->argc; i++) {
305 if (strcasecmp(ua->argk[i], _("jobid")) == 0) {
309 if (!(jcr=get_jcr_by_id(atoi(ua->argv[i])))) {
310 bsendmsg(ua, _("JobId %d is not running.\n"), atoi(ua->argv[i]));
314 } else if (strcasecmp(ua->argk[i], _("job")) == 0) {
318 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
319 bsendmsg(ua, _("Job %s is not running.\n"), ua->argv[i]);
325 /* If we still do not have a jcr,
326 * throw up a list and ask the user to select one.
329 /* Count Jobs running */
331 for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) {
332 if (jcr->JobId == 0) { /* this is us */
333 free_locked_jcr(jcr);
337 free_locked_jcr(jcr);
341 bsendmsg(ua, _("No Jobs running.\n"));
344 start_prompt(ua, _("Select Job:\n"));
346 for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
347 if (jcr->JobId == 0) { /* this is us */
348 free_locked_jcr(jcr);
351 add_prompt(ua, jcr->Job);
352 free_locked_jcr(jcr);
355 if (do_prompt(ua, _("Choose Job to cancel"), JobName) < 0) {
359 if (!get_cmd(ua, _("Confirm cancel (yes/no): "))) {
362 if (strcasecmp(ua->cmd, _("yes")) != 0) {
366 jcr = get_jcr_by_full_name(JobName);
368 bsendmsg(ua, _("Job %s not found.\n"), JobName);
373 switch (jcr->JobStatus) {
375 jcr->JobStatus = JS_Cancelled;
376 bsendmsg(ua, _("JobId %d, Job %s marked to be cancelled.\n"),
377 jcr->JobId, jcr->Job);
388 jcr->JobStatus = JS_Cancelled;
389 /* Cancel File daemon */
390 ua->jcr->client = jcr->client;
391 if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
392 bsendmsg(ua, _("Failed to connect to File daemon.\n"));
396 Dmsg0(200, "Connected to file daemon\n");
397 fd = ua->jcr->file_bsock;
398 bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
399 while (bnet_recv(fd) > 0) {
400 bsendmsg(ua, "%s", fd->msg);
402 bnet_sig(fd, BNET_TERMINATE);
404 ua->jcr->file_bsock = NULL;
406 /* Cancel Storage daemon */
407 ua->jcr->store = jcr->store;
408 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
409 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
413 Dmsg0(200, "Connected to storage daemon\n");
414 sd = ua->jcr->store_bsock;
415 bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
416 while (bnet_recv(sd) > 0) {
417 bsendmsg(ua, "%s", sd->msg);
419 bnet_sig(sd, BNET_TERMINATE);
421 ua->jcr->store_bsock = NULL;
424 bsendmsg(ua, _("JobId %d Job %s Status=%c cannot be cancelled.\n"),
425 jcr->JobId, jcr->Job, jcr->JobStatus);
433 * Create a pool record from a given Pool resource
434 * Also called from backup.c
435 * Returns: -1 on error
436 * 0 record already exists
440 int create_pool(B_DB *db, POOL *pool)
444 memset(&pr, 0, sizeof(POOL_DBR));
446 strcpy(pr.Name, pool->hdr.name);
448 if (db_get_pool_record(db, &pr)) {
449 return 0; /* exists */
452 strcpy(pr.PoolType, pool->pool_type);
453 pr.MaxVols = pool->max_volumes;
455 pr.UseOnce = pool->use_volume_once;
456 pr.UseCatalog = pool->use_catalog;
457 pr.AcceptAnyVolume = pool->accept_any_volume;
458 if (pool->label_format) {
459 strcpy(pr.LabelFormat, pool->label_format);
461 strcpy(pr.LabelFormat, "*"); /* none */
464 if (!db_create_pool_record(db, &pr)) {
465 return -1; /* error */
473 * Create a Pool Record in the database.
474 * It is always created from the Resource record.
476 static int createcmd(UAContext *ua, char *cmd)
484 pool = get_pool_resource(ua);
489 switch (create_pool(ua->db, pool)) {
491 bsendmsg(ua, _("Error: Pool %s already exists.\n\
492 Use update to change it.\n"), pool->hdr.name);
496 bsendmsg(ua, db_strerror(ua->db));
509 * Update a Pool Record in the database.
510 * It is always updated from the Resource record.
512 * update pool=<pool-name>
513 * updates pool from Pool resource
514 * update media pool=<pool-name> volume=<volume-name>
515 * changes pool info for volume
517 static int updatecmd(UAContext *ua, char *cmd)
519 static char *kw[] = {
529 switch (find_arg_keyword(ua, kw)) {
541 start_prompt(ua, _("Update choice:\n"));
542 add_prompt(ua, _("pool"));
543 add_prompt(ua, _("media"));
544 switch (do_prompt(ua, _("Choose catalog item to update"), NULL)) {
558 * Update a media record -- allows you to change the
559 * Volume status. E.g. if you want Bacula to stop
560 * writing on the volume, set it to anything other
563 static int update_media(UAContext *ua)
568 static char *kw[] = {
572 memset(&pr, 0, sizeof(pr));
573 memset(&mr, 0, sizeof(mr));
574 if (!get_pool_dbr(ua, &pr)) {
577 mr.PoolId = pr.PoolId;
578 mr.VolumeName[0] = 0;
580 i = find_arg_keyword(ua, kw);
581 if (i == 0 && ua->argv[i]) {
582 strcpy(mr.VolumeName, ua->argv[i]);
584 if (mr.VolumeName[0] == 0) {
585 db_list_media_records(ua->db, &mr, prtit, ua);
586 if (!get_cmd(ua, _("Enter Volume name to update: "))) {
589 strcpy(mr.VolumeName, ua->cmd);
592 if (!db_get_media_record(ua->db, &mr)) {
593 bsendmsg(ua, _("Media record for %s not found.\n"), mr.VolumeName);
596 start_prompt(ua, _("Volume Status Values:\n"));
597 add_prompt(ua, "Append");
598 add_prompt(ua, "Archive");
599 add_prompt(ua, "Disabled");
600 add_prompt(ua, "Full");
601 add_prompt(ua, "Recycle");
602 add_prompt(ua, "Read-Only");
603 if (do_prompt(ua, _("Choose new Volume Status"), ua->cmd) < 0) {
606 strcpy(mr.VolStatus, ua->cmd);
607 db_update_media_record(ua->db, &mr);
612 * Update pool record -- pull info from current POOL resource
614 static int update_pool(UAContext *ua)
620 memset(&pr, 0, sizeof(pr));
621 if (!get_pool_dbr(ua, &pr)) {
625 strcpy(pr.PoolType, pool->pool_type);
626 if (pr.MaxVols != (uint32_t) (pool->max_volumes)) {
627 pr.MaxVols = pool->max_volumes;
629 if (pr.MaxVols != 0 && pr.MaxVols < pr.NumVols) {
630 pr.MaxVols = pr.NumVols;
632 pr.UseOnce = pool->use_volume_once;
633 pr.UseCatalog = pool->use_catalog;
634 pr.AcceptAnyVolume = pool->accept_any_volume;
635 if (pool->label_format) {
636 strcpy(pr.LabelFormat, pool->label_format);
638 strcpy(pr.LabelFormat, "*"); /* none */
640 id = db_update_pool_record(ua->db, &pr);
642 bsendmsg(ua, "Error: db_update_pool_record returned %d\n", id);
648 static void do_storage_setdebug(UAContext *ua, STORE *store, int level)
652 ua->jcr->store = store;
653 /* Try connecting for up to 15 seconds */
654 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"),
655 store->hdr.name, store->address, store->SDport);
656 if (!connect_to_storage_daemon(ua->jcr, 1, 15, 0)) {
657 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
660 Dmsg0(20, _("Connected to storage daemon\n"));
661 sd = ua->jcr->store_bsock;
662 bnet_fsend(sd, "setdebug=%d\n", level);
663 if (bnet_recv(sd) > 0) {
664 bsendmsg(ua, "%s", sd->msg);
666 bnet_sig(sd, BNET_TERMINATE);
668 ua->jcr->store_bsock = NULL;
672 static void do_client_setdebug(UAContext *ua, CLIENT *client, int level)
676 /* Connect to File daemon */
678 ua->jcr->client = client;
679 /* Try to connect for 15 seconds */
680 bsendmsg(ua, _("Connecting to Client %s at %s:%d\n"),
681 client->hdr.name, client->address, client->FDport);
682 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
683 bsendmsg(ua, _("Failed to connect to Client.\n"));
686 Dmsg0(20, "Connected to file daemon\n");
687 fd = ua->jcr->file_bsock;
688 bnet_fsend(fd, "setdebug=%d\n", level);
689 if (bnet_recv(fd) > 0) {
690 bsendmsg(ua, "%s", fd->msg);
692 bnet_sig(fd, BNET_TERMINATE);
694 ua->jcr->file_bsock = NULL;
700 static void do_all_setdebug(UAContext *ua, int level)
702 STORE *store, **unique_store;
703 CLIENT *client, **unique_client;
709 /* Count Storage items */
712 for (i=0; (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)); i++)
714 unique_store = (STORE **) malloc(i * sizeof(STORE));
715 /* Find Unique Storage address/port */
716 store = (STORE *)GetNextRes(R_STORAGE, NULL);
718 unique_store[i++] = store;
719 while ((store = (STORE *)GetNextRes(R_STORAGE, (RES *)store))) {
721 for (j=0; j<i; j++) {
722 if (strcmp(unique_store[j]->address, store->address) == 0 &&
723 unique_store[j]->SDport == store->SDport) {
729 unique_store[i++] = store;
730 Dmsg2(40, "Stuffing: %s:%d\n", store->address, store->SDport);
735 /* Call each unique Storage daemon */
736 for (j=0; j<i; j++) {
737 do_storage_setdebug(ua, unique_store[j], level);
741 /* Count Client items */
744 for (i=0; (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)); i++)
746 unique_client = (CLIENT **) malloc(i * sizeof(CLIENT));
747 /* Find Unique Client address/port */
748 client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
750 unique_client[i++] = client;
751 while ((client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client))) {
753 for (j=0; j<i; j++) {
754 if (strcmp(unique_client[j]->address, client->address) == 0 &&
755 unique_client[j]->FDport == client->FDport) {
761 unique_client[i++] = client;
762 Dmsg2(40, "Stuffing: %s:%d\n", client->address, client->FDport);
767 /* Call each unique File daemon */
768 for (j=0; j<i; j++) {
769 do_client_setdebug(ua, unique_client[j], level);
775 * setdebug level=nn all
777 static int setdebugcmd(UAContext *ua, char *cmd)
787 Dmsg1(20, "setdebug:%s:\n", cmd);
790 for (i=1; i<ua->argc; i++) {
791 if (strcasecmp(ua->argk[i], _("level")) == 0 && ua->argv[i]) {
792 level = atoi(ua->argv[i]);
797 if (!get_cmd(ua, _("Enter new debug level: "))) {
800 level = atoi(ua->cmd);
803 bsendmsg(ua, _("level cannot be negative.\n"));
808 for (i=1; i<ua->argc; i++) {
809 if (strcasecmp(ua->argk[i], _("all")) == 0) {
810 do_all_setdebug(ua, level);
813 if (strcasecmp(ua->argk[i], _("dir")) == 0 ||
814 strcasecmp(ua->argk[i], _("director")) == 0) {
818 if (strcasecmp(ua->argk[i], _("client")) == 0) {
821 client = (CLIENT *) GetResWithName(R_CLIENT, ua->argv[i]);
823 do_client_setdebug(ua, client, level);
827 client = select_client_resource(ua);
829 do_client_setdebug(ua, client, level);
833 store = get_storage_resource(ua, cmd);
835 do_storage_setdebug(ua, store, level);
841 * We didn't find an appropriate keyword above, so
844 start_prompt(ua, _("Available daemons are: \n"));
845 add_prompt(ua, _("Director"));
846 add_prompt(ua, _("Storage"));
847 add_prompt(ua, _("Client"));
848 add_prompt(ua, _("All"));
849 switch(do_prompt(ua, _("Select daemon type to set debug level"), NULL)) {
850 case 0: /* Director */
854 store = get_storage_resource(ua, cmd);
856 do_storage_setdebug(ua, store, level);
860 client = select_client_resource(ua);
862 do_client_setdebug(ua, client, level);
866 do_all_setdebug(ua, level);
877 * Delete Pool records (should purge Media with it).
879 * delete pool=<pool-name>
880 * delete media pool=<pool-name> volume=<name>
882 static int deletecmd(UAContext *ua, char *cmd)
884 static char *keywords[] = {
894 "In general it is not a good idea to delete either a\n"
895 "Pool or Media since in both cases, you may delete Media\n"
896 "that contain data.\n\n"));
898 switch (find_arg_keyword(ua, keywords)) {
908 switch (do_keyword_prompt(ua, _("Choose catalog item to delete"), keywords)) {
916 bsendmsg(ua, _("Nothing done.\n"));
923 * Delete media records from database -- dangerous
925 static int delete_media(UAContext *ua)
932 memset(&pr, 0, sizeof(pr));
933 memset(&mr, 0, sizeof(mr));
935 /* Get the pool, possibly from pool=<pool-name> */
936 if (!get_pool_dbr(ua, &pr)) {
939 mr.PoolId = pr.PoolId;
941 /* See if a volume name is specified as an argument */
942 for (i=1; i<ua->argc; i++) {
943 if (strcasecmp(ua->argk[i], _("volume")) == 0 && ua->argv[i]) {
949 strcpy(mr.VolumeName, ua->argv[i]);
951 db_list_media_records(ua->db, &mr, prtit, ua);
952 if (!get_cmd(ua, _("Enter the Volume name to delete: "))) {
957 strcpy(mr.VolumeName, ua->cmd);
958 if (!get_cmd(ua, _("If you want to continue enter pretty please: "))) {
961 if (strcmp(ua->cmd, _("pretty please")) == 0) {
962 db_delete_media_record(ua->db, &mr);
968 * Delete a pool record from the database -- dangerous
970 static int delete_pool(UAContext *ua)
974 memset(&pr, 0, sizeof(pr));
976 if (!get_pool_dbr(ua, &pr)) {
979 if (!get_cmd(ua, _("If you want to continue enter pretty please: "))) {
982 if (strcmp(ua->cmd, _("pretty please")) == 0) {
983 db_delete_pool_record(ua->db, &pr);
992 * label storage=xxx volume=vvv
994 static int labelcmd(UAContext *ua, char *cmd)
998 char dev_name[MAX_NAME_LENGTH];
1002 int mounted = FALSE;
1004 static char *keyword[] = {
1011 store = get_storage_resource(ua, cmd);
1016 i = find_arg_keyword(ua, keyword);
1017 if (i >=0 && ua->argv[i]) {
1018 strcpy(ua->cmd, ua->argv[i]);
1023 if (!get_cmd(ua, _("Enter new Volume name: "))) {
1027 if (strchr(ua->cmd, '|')) {
1028 bsendmsg(ua, _("Illegal character | in a volume name.\n"));
1031 if (strlen(ua->cmd) >= MAX_NAME_LENGTH) {
1032 bsendmsg(ua, _("Volume name too long.\n"));
1036 memset(&mr, 0, sizeof(mr));
1037 strcpy(mr.VolumeName, ua->cmd);
1038 if (db_get_media_record(ua->db, &mr)) {
1039 bsendmsg(ua, _("Media record for Volume %s already exists.\n"),
1043 strcpy(mr.MediaType, store->media_type);
1045 memset(&pr, 0, sizeof(pr));
1046 if (!select_pool_dbr(ua, &pr)) {
1049 mr.PoolId = pr.PoolId;
1050 strcpy(mr.Recycle, "Yes");
1051 strcpy(mr.VolStatus, "Append");
1053 ua->jcr->store = store;
1054 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
1055 store->hdr.name, store->address, store->SDport);
1056 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
1057 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
1060 sd = ua->jcr->store_bsock;
1061 strcpy(dev_name, store->dev_name);
1062 bash_spaces(dev_name);
1063 bash_spaces(mr.VolumeName);
1064 bash_spaces(mr.MediaType);
1065 bash_spaces(pr.Name);
1066 bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s"),
1067 dev_name, mr.VolumeName, pr.Name, mr.MediaType);
1068 bsendmsg(ua, "Sending label command ...\n");
1069 while (bnet_recv(sd) > 0) {
1070 bsendmsg(ua, "%s", sd->msg);
1071 if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
1075 ua->jcr->store_bsock = NULL;
1076 unbash_spaces(dev_name);
1077 unbash_spaces(mr.VolumeName);
1078 unbash_spaces(mr.MediaType);
1079 unbash_spaces(pr.Name);
1081 if (db_create_media_record(ua->db, &mr)) {
1082 bsendmsg(ua, _("Media record for Volume=%s successfully created.\n"),
1084 if (ua->automount) {
1085 bsendmsg(ua, _("Requesting mount %s ...\n"), dev_name);
1086 bnet_fsend(sd, "mount %s", dev_name);
1087 while (bnet_recv(sd) > 0) {
1088 bsendmsg(ua, "%s", sd->msg);
1090 * 3001 OK mount. Device=xxx or
1091 * 3001 Mounted Volume vvvv
1093 if (strncmp(sd->msg, "3001 ", 5) == 0) {
1095 /***** ****FIXME***** find job waiting for
1096 ***** mount, and change to waiting for SD
1102 bsendmsg(ua, "%s", db_strerror(ua->db));
1106 bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
1108 bnet_sig(sd, BNET_TERMINATE);
1113 static void do_mount_cmd(int mount, UAContext *ua, char *cmd)
1117 char dev_name[MAX_NAME_LENGTH];
1123 Dmsg1(20, "mount: %s\n", ua->UA_sock->msg);
1125 store = get_storage_resource(ua, cmd);
1130 Dmsg2(20, "Found storage, MediaType=%s DevName=%s\n",
1131 store->media_type, store->dev_name);
1133 ua->jcr->store = store;
1134 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
1135 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
1138 sd = ua->jcr->store_bsock;
1139 strcpy(dev_name, store->dev_name);
1140 bash_spaces(dev_name);
1142 bnet_fsend(sd, "mount %s", dev_name);
1144 bnet_fsend(sd, "unmount %s", dev_name);
1146 while (bnet_recv(sd) > 0) {
1147 bsendmsg(ua, "%s", sd->msg);
1148 if (strncmp(sd->msg, "3001 OK mount.", 14) == 0) {
1149 /***** ****FIXME**** fix JobStatus */
1152 bnet_sig(sd, BNET_TERMINATE);
1154 ua->jcr->store_bsock = NULL;
1158 * mount [storage | device] <name>
1160 static int mountcmd(UAContext *ua, char *cmd)
1162 do_mount_cmd(1, ua, cmd); /* mount */
1168 * unmount [storage | device] <name>
1170 static int unmountcmd(UAContext *ua, char *cmd)
1172 do_mount_cmd(0, ua, cmd); /* unmount */
1179 * use catalog=<name>
1181 static int usecmd(UAContext *ua, char *cmd)
1183 CAT *oldcatalog, *catalog;
1186 close_db(ua); /* close any previously open db */
1187 oldcatalog = ua->catalog;
1189 if (!(catalog = get_catalog_resource(ua))) {
1190 ua->catalog = oldcatalog;
1192 ua->catalog = catalog;
1195 bsendmsg(ua, _("Using Catalog name=%s DB=%s\n"),
1196 ua->catalog->hdr.name, ua->catalog->db_name);
1201 int quitcmd(UAContext *ua, char *cmd)
1206 static int helpcmd(UAContext *ua, char *cmd)
1211 bnet_fsend(ua->UA_sock, _(" Command Description\n ======= ===========\n"));
1212 for (i=0; i<comsize; i++) {
1213 bnet_fsend(ua->UA_sock, _(" %-10s %s\n"), _(commands[i].key), _(commands[i].help));
1215 bnet_fsend(ua->UA_sock, "\n");
1219 static int versioncmd(UAContext *ua, char *cmd)
1221 bsendmsg(ua, "%s Version: " VERSION " (" DATE ")\n", my_name);
1226 /* A bit brain damaged in that if the user has not done
1227 * a "use catalog xxx" command, we simply find the first
1228 * catalog resource and open it.
1230 int open_db(UAContext *ua)
1237 ua->catalog = (CAT *)GetNextRes(R_CATALOG, NULL);
1240 bnet_fsend(ua->UA_sock, _("Could not find a Catalog resource\n"));
1243 bnet_fsend(ua->UA_sock, _("Using default Catalog name=%s DB=%s\n"),
1244 ua->catalog->hdr.name, ua->catalog->db_name);
1248 Dmsg0(50, "Open database\n");
1249 ua->db = db_init_database(ua->catalog->db_name, ua->catalog->db_user,
1250 ua->catalog->db_password);
1251 if (!db_open_database(ua->db)) {
1252 bnet_fsend(ua->UA_sock, _("Could not open DB %s: ERR=%s"),
1253 ua->catalog->db_name, db_strerror(ua->db));
1257 Dmsg1(50, "DB %s opened\n", ua->catalog->db_name);
1261 void close_db(UAContext *ua)
1264 db_close_database(ua->db);