(addr: A, password: Option) -> Self {
293 | let addr = addr.to_string();
294 | let password = password.map(|p| p.to_string());
295 | Self {
296 | state: Arc::new(Mutex::new(Some(ConnState::Connecting(Box::pin(
297 | DaemonStream::connect(addr, password),
298 | ))))),
299 | }
300 | }
301 | }
302 |
303 | impl tower::Service> for Transport {
304 | type Response = Vec;
305 | type Error = Error;
306 | type Future = Pin>>>;
307 |
308 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> {
309 | let mut g = match self.state.try_lock() {
310 | Ok(g) => g,
311 | Err(e) => { return Poll::Pending; }
312 | };
313 |
314 | let (state, out) = match g.take().unwrap() {
315 | ConnState::Connecting(mut future) => {
316 | let res = future.as_mut().poll(cx);
317 | match res {
318 | Poll::Pending => (Some(ConnState::Connecting(future)), Poll::Pending),
319 | Poll::Ready(Ok(conn)) => (Some(ConnState::Ready(conn)), Poll::Ready(Ok(()))),
320 | Poll::Ready(Err(e)) => (None, Poll::Ready(Err(e))),
321 | }
322 | }
323 | ConnState::Ready(conn) => (Some(ConnState::Ready(conn)), Poll::Ready(Ok(()))),
324 | ConnState::Error(error) => (
325 | Some(ConnState::Error(error.clone())),
326 | Poll::Ready(Err(error)),
327 | ),
328 | };
329 |
330 | *g = state;
331 | out
332 | }
333 |
334 | fn call(&mut self, req: Vec) -> Self::Future {
335 | let state = self.state.clone();
336 | Box::pin(async move {
337 | let mut state = state.lock().await;
338 | let mut conn = match state.take() {
339 | Some(ConnState::Ready(conn)) => conn,
340 | _ => unreachable!(),
341 | };
342 | let query_res = conn.query(req).await;
343 | if let Err(e) = &query_res {
344 | *state = Some(ConnState::Error(e.clone()));
345 | } else {
346 | *state = Some(ConnState::Ready(conn));
347 | }
348 | query_res
349 | })
350 | }
351 | }
352 |
353 | pub struct Client {
354 | transport: S,
355 | }
356 |
357 | impl Client
358 | where
359 | S: tower::Service, Response=Vec, Error=Error>,
360 | {
361 | pub fn new(transport: S) -> Self {
362 | Self { transport }
363 | }
364 |
365 | async fn get_object From<&'a treexml::Element>>(
366 | &mut self,
367 | req_data: Vec,
368 | object_tag: &str,
369 | ) -> Result {
370 | self.transport.ready().await?;
371 | let data = self.transport.call(req_data).await?;
372 | verify_rpc_reply_contents(&data)?;
373 | for child in &data {
374 | if child.name == object_tag {
375 | return Ok(T::from(child));
376 | }
377 | }
378 | Err(Error::DataParseError("Object not found.".to_string()))
379 | }
380 |
381 | async fn get_object_by_req_tag From<&'a treexml::Element>>(
382 | &mut self,
383 | req_tag: &str,
384 | object_tag: &str,
385 | ) -> Result {
386 | self.get_object(vec![treexml::Element::new(req_tag)], object_tag)
387 | .await
388 | }
389 |
390 | async fn get_vec From<&'a treexml::Element>>(
391 | &mut self,
392 | req_data: Vec,
393 | vec_tag: &str,
394 | object_tag: &str,
395 | ) -> Result, Error> {
396 | let mut v = Vec::new();
397 | {
398 | self.transport.ready().await?;
399 | let data = self.transport.call(req_data).await?;
400 | verify_rpc_reply_contents(&data)?;
401 | let mut success = false;
402 | for child in data {
403 | if child.name == vec_tag {
404 | success = true;
405 | for vec_child in &child.children {
406 | if vec_child.name == object_tag {
407 | v.push(T::from(vec_child));
408 | }
409 | }
410 | }
411 | }
412 | if !success {
413 | return Err(Error::DataParseError("Objects not found.".to_string()));
414 | }
415 | }
416 | Ok(v)
417 | }
418 |
419 | async fn get_vec_by_req_tag From<&'a treexml::Element>>(
420 | &mut self,
421 | req_tag: &str,
422 | vec_tag: &str,
423 | object_tag: &str,
424 | ) -> Result, Error> {
425 | self.get_vec(vec![treexml::Element::new(req_tag)], vec_tag, object_tag)
426 | .await
427 | }
428 |
429 | pub async fn get_messages(&mut self, seqno: i64) -> Result, Error> {
430 | self.get_vec(
431 | vec![{
432 | let mut node = treexml::Element::new("get_messages");
433 | node.text = Some(format!("{}", seqno));
434 | node
435 | }],
436 | "msgs",
437 | "msg",
438 | )
439 | .await
440 | }
441 |
442 | pub async fn get_projects(&mut self) -> Result, Error> {
443 | self.get_vec_by_req_tag("get_all_projects_list", "projects", "project")
444 | .await
445 | }
446 |
447 | pub async fn get_account_manager_info(&mut self) -> Result {
448 | self.get_object_by_req_tag("acct_mgr_info", "acct_mgr_info")
449 | .await
450 | }
451 |
452 | pub async fn get_account_manager_rpc_status(&mut self) -> Result {
453 | self.transport.ready().await?;
454 | let data = self
455 | .transport
456 | .call(vec![treexml::Element::new("acct_mgr_rpc_poll")])
457 | .await?;
458 | verify_rpc_reply_contents(&data)?;
459 |
460 | let mut v: Option = None;
461 | for child in &data {
462 | if &*child.name == "acct_mgr_rpc_reply" {
463 | for c in &child.children {
464 | if &*c.name == "error_num" {
465 | v = util::eval_node_contents(c);
466 | }
467 | }
468 | }
469 | }
470 | v.ok_or_else(|| Error::DataParseError("acct_mgr_rpc_reply node not found".into()))
471 | }
472 |
473 | pub async fn connect_to_account_manager(
474 | &mut self,
475 | url: &str,
476 | name: &str,
477 | password: &str,
478 | ) -> Result {
479 | let mut req_node = treexml::Element::new("acct_mgr_rpc");
480 | req_node.children = vec![
481 | {
482 | let mut node = treexml::Element::new("url");
483 | node.text = Some(url.into());
484 | node
485 | },
486 | {
487 | let mut node = treexml::Element::new("name");
488 | node.text = Some(name.into());
489 | node
490 | },
491 | {
492 | let mut node = treexml::Element::new("password");
493 | node.text = Some(password.into());
494 | node
495 | },
496 | ];
497 | self.transport.ready().await?;
498 | let root_node = self.transport.call(vec![req_node]).await?;
499 | Ok(verify_rpc_reply_contents(&root_node)?)
500 | }
501 |
502 | pub async fn exchange_versions(
503 | &mut self,
504 | info: &models::VersionInfo,
505 | ) -> Result {
506 | let mut content_node = treexml::Element::new("exchange_versions");
507 | {
508 | let mut node = treexml::Element::new("major");
509 | node.text = info.minor.map(|v| format!("{}", v));
510 | content_node.children.push(node);
511 | }
512 | {
513 | let mut node = treexml::Element::new("minor");
514 | node.text = info.major.map(|v| format!("{}", v));
515 | content_node.children.push(node);
516 | }
517 | {
518 | let mut node = treexml::Element::new("release");
519 | node.text = info.release.map(|v| format!("{}", v));
520 | content_node.children.push(node);
521 | }
522 | self.get_object(vec![content_node], "server_version").await
523 | }
524 |
525 | pub async fn get_results(
526 | &mut self,
527 | active_only: bool,
528 | ) -> Result, Error> {
529 | self.get_vec(
530 | vec![{
531 | let mut node = treexml::Element::new("get_results");
532 | if active_only {
533 | let mut ao_node = treexml::Element::new("active_only");
534 | ao_node.text = Some("1".into());
535 | node.children.push(ao_node);
536 | }
537 | node
538 | }],
539 | "results",
540 | "result",
541 | )
542 | .await
543 | }
544 |
545 | pub async fn set_mode(
546 | &mut self,
547 | c: models::Component,
548 | m: models::RunMode,
549 | duration: f64,
550 | ) -> Result<(), Error> {
551 | self.transport.ready().await?;
552 | let rsp_root = self
553 | .transport
554 | .call(vec![{
555 | let comp_desc = match c {
556 | models::Component::CPU => "run",
557 | models::Component::GPU => "gpu",
558 | models::Component::Network => "network",
559 | }
560 | .to_string();
561 | let mode_desc = match m {
562 | models::RunMode::Always => "always",
563 | models::RunMode::Auto => "auto",
564 | models::RunMode::Never => "never",
565 | models::RunMode::Restore => "restore",
566 | }
567 | .to_string();
568 |
569 | let mut node = treexml::Element::new(format!("set_{}_mode", &comp_desc));
570 | let mut dur_node = treexml::Element::new("duration");
571 | dur_node.text = Some(format!("{}", duration));
572 | node.children.push(dur_node);
573 | node.children.push(treexml::Element::new(mode_desc));
574 | node
575 | }])
576 | .await?;
577 | verify_rpc_reply_contents(&rsp_root)?;
578 | Ok(())
579 | }
580 |
581 | pub async fn get_host_info(&mut self) -> Result {
582 | self.get_object_by_req_tag("get_host_info", "host_info")
583 | .await
584 | }
585 |
586 | pub async fn set_language(&mut self, v: &str) -> Result<(), Error> {
587 | self.transport.ready().await?;
588 | verify_rpc_reply_contents(
589 | &self
590 | .transport
591 | .call(vec![{
592 | let mut node = treexml::Element::new("set_language");
593 | let mut language_node = treexml::Element::new("language");
594 | language_node.text = Some(v.into());
595 | node.children.push(language_node);
596 | node
597 | }])
598 | .await?,
599 | )?;
600 | Ok(())
601 | }
602 | }
603 |
604 | #[cfg(test)]
605 | mod tests {
606 | use super::errors::Error;
607 |
608 | #[test]
609 | fn verify_rpc_reply_contents() {
610 | let mut fixture = treexml::Element::new("error");
611 | fixture.text = Some("Missing authenticator".into());
612 | let fixture = vec![fixture];
613 | assert_eq!(
614 | super::verify_rpc_reply_contents(&fixture).err().unwrap(),
615 | Error::AuthError("Missing authenticator".to_string())
616 | );
617 | }
618 | }
619 |
--------------------------------------------------------------------------------