Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndma_cops_robot.c
1 /*
2  * Copyright (c) 1998,1999,2000
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36
37
38 #include "ndmagents.h"
39
40
41 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
42
43
44 int
45 ndmca_op_robot_remedy (struct ndm_session *sess)
46 {
47         struct ndm_job_param *  job = &sess->control_acb.job;
48         int                     rc;
49
50         if (!job->have_robot)
51                 return 0;
52
53         rc = ndmca_connect_robot_agent (sess);
54         if (rc) return rc;      /* already tattled */
55
56         rc = ndmca_robot_prep_target (sess);
57         if (rc) return rc;      /* already tattled */
58
59         rc = ndmca_robot_check_ready (sess);
60         if (rc) {       /* already tattled */
61                 ndmalogf (sess, 0, 0, "Robot is not ready, trying to remedy");
62                 rc = ndmca_robot_remedy_ready (sess);
63                 if (rc) {
64                         ndmalogf (sess, 0, 0, "Robot remedy failed");
65                         return -1;
66                 }
67         }
68
69         return 0;
70 }
71
72 int
73 ndmca_op_robot_startup (struct ndm_session *sess, int verify_media_flag)
74 {
75         struct ndm_job_param *  job = &sess->control_acb.job;
76         int                     rc;
77
78         if (!job->have_robot)
79                 return 0;
80
81         rc = ndmca_connect_robot_agent (sess);
82         if (rc) return rc;      /* already tattled */
83
84         rc = ndmca_robot_prep_target (sess);
85         if (rc) return rc;      /* already tattled */
86
87         rc = ndmca_robot_check_ready (sess);
88         if (rc) {       /* already tattled */
89                 if (!job->auto_remedy) {
90                         ndmalogf (sess, 0, 0, "Robot is not ready, failing");
91                         return -1;
92                 }
93                 ndmalogf (sess, 0, 0, "Robot is not ready, trying to remedy");
94                 rc = ndmca_robot_remedy_ready (sess);
95                 if (rc) {
96                         ndmalogf (sess, 0, 0, "Robot remedy failed");
97                         return -1;
98                 }
99         }
100
101         if (verify_media_flag) {
102                 rc = ndmca_media_verify (sess);
103                 if (rc) return rc;      /* already tattled */
104         }
105
106         return 0;
107 }
108
109 /*
110  * ndmca_op_rewind_tape() and ndmca_op_eject_tape() really
111  * belong somewhere else. Here because they are close
112  * to the other "tape handling" operations.
113  */
114
115 int
116 ndmca_op_rewind_tape (struct ndm_session *sess)
117 {
118         return ndmca_op_mtio (sess, NDMP9_MTIO_REW);
119 }
120
121 int
122 ndmca_op_eject_tape (struct ndm_session *sess)
123 {
124         return ndmca_op_mtio (sess, NDMP9_MTIO_OFF);
125 }
126
127
128 int
129 ndmca_op_mtio (struct ndm_session *sess, ndmp9_tape_mtio_op mtio_op)
130 {
131         struct ndm_control_agent *ca = &sess->control_acb;
132         int                     rc;
133
134         ca->tape_mode = NDMP9_TAPE_READ_MODE;
135         ca->is_label_op = 1;
136
137         rc = ndmca_connect_tape_agent (sess);
138         if (rc) {
139                 ndmconn_destruct (sess->plumb.tape);
140                 return rc;      /* already tattled */
141         }
142
143         rc = ndmca_media_open_tape (sess);
144         if (rc) return rc;      /* already tattled */
145
146         if (mtio_op == NDMP9_MTIO_OFF) {
147                 /* best-effort rewind */
148                 ndmca_media_mtio_tape (sess, NDMP9_MTIO_REW, 1, 0);
149         }
150
151         rc = ndmca_media_mtio_tape (sess, mtio_op, 1, 0);
152         if (rc) {
153                 /* best-effort close */
154                 ndmca_media_close_tape (sess);
155                 return rc;      /* already tattled */
156         }
157
158         rc = ndmca_media_close_tape (sess);
159         if (rc) return rc;      /* already tattled */
160
161         return 0;
162 }
163
164 int
165 ndmca_op_move_tape (struct ndm_session *sess)
166 {
167         struct ndm_control_agent *ca = &sess->control_acb;
168         struct ndm_job_param *  job = &ca->job;
169         int                     src_addr = job->from_addr;
170         int                     dst_addr = job->to_addr;
171         int                     rc;
172
173         /* repeat audits */
174         if (!job->to_addr_given || !job->from_addr_given) {
175                 ndmalogf (sess, 0, 0, "Missing to/from addr");
176                 return -1;
177         }
178
179         rc = ndmca_robot_startup (sess);
180         if (rc) return rc;      /* already tattled -- NOT */
181
182         rc = ndmca_robot_obtain_info (sess);
183         if (rc) return rc;      /* already tattled -- NOT */
184
185         rc = ndmca_robot_move (sess, src_addr, dst_addr);
186         if (rc) return rc;      /* already tattled */
187
188         return 0;
189 }
190
191 int
192 ndmca_op_import_tape (struct ndm_session *sess)
193 {
194         struct ndm_control_agent *ca = &sess->control_acb;
195         struct ndm_job_param *  job = &ca->job;
196         struct smc_ctrl_block * smc = &ca->smc_cb;
197         int                     src_addr;
198         int                     dst_addr = job->to_addr;
199         int                     rc;
200
201         /* repeat audits */
202         if (!job->to_addr_given) {
203                 ndmalogf (sess, 0, 0, "Missing to-addr");
204                 return -1;
205         }
206
207         rc = ndmca_robot_startup (sess);
208         if (rc) return rc;      /* already tattled -- NOT */
209
210         rc = ndmca_robot_obtain_info (sess);
211         if (rc) return rc;      /* already tattled -- NOT */
212
213         if (smc->elem_aa.iee_count < 1) {
214                 ndmalogf (sess, 0, 0, "robot has no import/export; try move");
215                 return -1;
216         }
217         src_addr = smc->elem_aa.iee_addr;
218
219         rc = ndmca_robot_move (sess, src_addr, dst_addr);
220         if (rc) return rc;      /* already tattled */
221
222         return 0;
223 }
224
225 int
226 ndmca_op_export_tape (struct ndm_session *sess)
227 {
228         struct ndm_control_agent *ca = &sess->control_acb;
229         struct ndm_job_param *  job = &ca->job;
230         struct smc_ctrl_block * smc = &ca->smc_cb;
231         int                     src_addr = job->from_addr;
232         int                     dst_addr;
233         int                     rc;
234
235         /* repeat audits */
236         if (!job->from_addr_given) {
237                 ndmalogf (sess, 0, 0, "Missing from-addr");
238                 return -1;
239         }
240
241         rc = ndmca_robot_startup (sess);
242         if (rc) return rc;      /* already tattled -- NOT */
243
244         rc = ndmca_robot_obtain_info (sess);
245         if (rc) return rc;      /* already tattled -- NOT */
246
247         if (smc->elem_aa.iee_count < 1) {
248                 ndmalogf (sess, 0, 0, "robot has no import/export; try move");
249                 return -1;
250         }
251         dst_addr = smc->elem_aa.iee_addr;
252
253         rc = ndmca_robot_move (sess, src_addr, dst_addr);
254         if (rc) return rc;      /* already tattled */
255
256         return 0;
257 }
258
259 int
260 ndmca_op_load_tape (struct ndm_session *sess)
261 {
262         struct ndm_control_agent *ca = &sess->control_acb;
263         struct ndm_job_param *  job = &ca->job;
264         struct smc_ctrl_block * smc = &ca->smc_cb;
265         int                     src_addr = job->from_addr;
266         int                     dst_addr;
267         int                     rc;
268
269         /* repeat audits */
270         if (!job->from_addr_given) {
271                 ndmalogf (sess, 0, 0, "Missing from-addr");
272                 return -1;
273         }
274
275         rc = ndmca_robot_startup (sess);
276         if (rc) return rc;      /* already tattled -- NOT */
277
278         rc = ndmca_robot_obtain_info (sess);
279         if (rc) return rc;      /* already tattled -- NOT */
280
281         if (job->drive_addr_given) {
282                 dst_addr = job->drive_addr;
283         } else if (smc->elem_aa.dte_count > 0) {
284                 dst_addr = smc->elem_aa.dte_addr;
285         } else {
286                 ndmalogf (sess, 0, 0, "robot has no tape drives? try move");
287                 return -1;
288         }
289
290         /*
291          * Calculation for dst_addr repeated in ndmca_robot_load().
292          * We just did it to be sure it would succeed
293          */
294
295         rc = ndmca_robot_load (sess, src_addr);
296         if (rc) return rc;      /* already tattled */
297
298         return 0;
299 }
300
301 int
302 ndmca_op_unload_tape (struct ndm_session *sess)
303 {
304         struct ndm_control_agent *ca = &sess->control_acb;
305         struct ndm_job_param *  job = &ca->job;
306         struct smc_ctrl_block * smc = &ca->smc_cb;
307         int                     src_addr = job->from_addr;
308         int                     dst_addr;
309         int                     rc;
310
311         /* repeat audits */
312         rc = ndmca_robot_startup (sess);
313         if (rc) return rc;      /* already tattled -- NOT */
314
315         rc = ndmca_robot_obtain_info (sess);
316         if (rc) return rc;      /* already tattled -- NOT */
317
318         if (job->drive_addr_given) {
319                 src_addr = job->drive_addr;
320         } else if (smc->elem_aa.dte_count > 0) {
321                 src_addr = smc->elem_aa.dte_addr;
322         } else {
323                 ndmalogf (sess, 0, 0, "robot has no tape drives? try move");
324                 return -1;
325         }
326
327         /*
328          * Calculation for src_addr repeated in ndmca_robot_unload().
329          * We just did it to be sure it would succeed
330          */
331
332         if (job->tape_device) {
333                 /* best effort */
334                 rc = ndmca_op_mtio (sess, job->use_eject
335                                             ? NDMP9_MTIO_OFF : NDMP9_MTIO_REW);
336         }
337
338         if (job->to_addr_given) {
339                 dst_addr = job->to_addr;
340         } else {
341                 struct smc_element_descriptor * edp;
342                 struct smc_element_descriptor * edp2;
343                 char                            prefix[60];
344
345                 /*
346                  * Try to automatically determine where to
347                  * put the tape, if there is one in the drive.
348                  * This is pretty much a rip-off of remedy_robot().
349                  * The difference is here we believe the user
350                  * that something should happen. Otherwise,
351                  * the user would have used REMEDY_ROBOT.
352                  */
353
354                 edp = ndmca_robot_find_element (sess, src_addr);
355                 if (!edp) {
356                         ndmalogf (sess, 0, 1,
357                                 "no such slot @%d, trying unload anyway",
358                                 src_addr);
359                         dst_addr = 0;           /* g'luck! */
360                         goto unload_anyway;
361                 }
362
363                 if (!edp->Full) {
364                         ndmalogf (sess, 0, 1,
365                                 "drive @%d empty, trying unload anyway",
366                                 src_addr);
367                         dst_addr = 0;           /* g'luck! */
368                         goto unload_anyway;
369                 }
370
371                 sprintf (prefix, "drive @%d full", edp->element_address);
372
373                 if (!edp->SValid) {
374                         ndmalogf (sess, 0, 1,
375                                 "%s, no SValid info, you must specify to-addr",
376                                 prefix);
377                         return -1;
378                 }
379
380                 dst_addr = edp->src_se_addr;
381
382                 sprintf (NDMOS_API_STREND(prefix), ", src @%d",
383                                                         edp->src_se_addr);
384
385                 edp2 = ndmca_robot_find_element (sess, dst_addr);
386                 if (!edp2) {
387                         ndmalogf (sess, 0, 1,
388                                 "%s, no such addr, trying unload anyway",
389                                 prefix);
390                         goto unload_anyway;
391                 }
392
393                 if (edp2->element_type_code != SMC_ELEM_TYPE_SE) {
394                         ndmalogf (sess, 0, 1,
395                                 "%s, not slot, trying unload anyway", prefix);
396                         goto unload_anyway;
397                 }
398
399                 if (edp2->Full) {
400                         ndmalogf (sess, 0, 1,
401                                 "%s, slot Full, trying unload anyway", prefix);
402                         goto unload_anyway;
403                 }
404         }
405
406
407   unload_anyway:
408         rc = ndmca_robot_unload (sess, dst_addr);
409         if (rc) return rc;      /* already tattled */
410
411         return 0;
412 }
413
414 int
415 ndmca_op_init_elem_status (struct ndm_session *sess)
416 {
417         int                     rc;
418
419         /* repeat audits */
420         rc = ndmca_robot_startup (sess);
421         if (rc) return rc;      /* already tattled -- NOT */
422
423         /* best-effort */
424         rc = ndmca_robot_obtain_info (sess);
425
426         rc = ndmca_robot_init_elem_status (sess);
427         if (rc) return rc;      /* already tattled */
428
429         rc = ndmca_robot_query (sess);
430         if (rc) return rc;      /* already tattled -- WAY WAY tattled */
431
432         return 0;
433 }
434
435 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */