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
ndmca_op_robot_remedy(struct ndm_session * sess)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
ndmca_op_robot_startup(struct ndm_session * sess,int verify_media_flag)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
ndmca_op_rewind_tape(struct ndm_session * sess)116 ndmca_op_rewind_tape (struct ndm_session *sess)
117 {
118 return ndmca_op_mtio (sess, NDMP9_MTIO_REW);
119 }
120
121 int
ndmca_op_eject_tape(struct ndm_session * sess)122 ndmca_op_eject_tape (struct ndm_session *sess)
123 {
124 return ndmca_op_mtio (sess, NDMP9_MTIO_OFF);
125 }
126
127
128 int
ndmca_op_mtio(struct ndm_session * sess,ndmp9_tape_mtio_op mtio_op)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
ndmca_op_move_tape(struct ndm_session * sess)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
ndmca_op_import_tape(struct ndm_session * sess)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
ndmca_op_export_tape(struct ndm_session * sess)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
ndmca_op_load_tape(struct ndm_session * sess)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
ndmca_op_unload_tape(struct ndm_session * sess)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
ndmca_op_init_elem_status(struct ndm_session * sess)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 */
436