- Monitors do not probe storage. - Manager decides if probing is needed, ensuring it is done as part of the SetConfig action.
219 lines
6.4 KiB
Rust
219 lines
6.4 KiB
Rust
// Copyright (c) [2026] SUSE LLC
|
|
//
|
|
// All Rights Reserved.
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
// more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program; if not, contact SUSE LLC.
|
|
//
|
|
// To contact SUSE LLC about this file by physical or electronic mail, you may
|
|
// find current contact information at www.suse.com.
|
|
|
|
use crate::{
|
|
dasd::{self, client::DASDClient},
|
|
message, storage_client,
|
|
zfcp::{self, client::ZFCPClient},
|
|
};
|
|
use agama_utils::{
|
|
actor::{self, Actor, Handler, MessageHandler},
|
|
api::{
|
|
event,
|
|
s390::{Config, SystemInfo},
|
|
},
|
|
issue, progress, BoxFuture,
|
|
};
|
|
use async_trait::async_trait;
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum Error {
|
|
#[error(transparent)]
|
|
Actor(#[from] actor::Error),
|
|
#[error(transparent)]
|
|
DASDClient(#[from] dasd::client::Error),
|
|
#[error(transparent)]
|
|
ZFCPClient(#[from] zfcp::client::Error),
|
|
#[error(transparent)]
|
|
DASDMonitor(#[from] dasd::monitor::Error),
|
|
#[error(transparent)]
|
|
ZFCPMonitor(#[from] zfcp::monitor::Error),
|
|
#[error(transparent)]
|
|
StorageClient(#[from] storage_client::Error),
|
|
}
|
|
|
|
pub struct Starter {
|
|
events: event::Sender,
|
|
progress: Handler<progress::Service>,
|
|
issues: Handler<issue::Service>,
|
|
connection: zbus::Connection,
|
|
dasd: Option<Box<dyn DASDClient + Send + 'static>>,
|
|
zfcp: Option<Box<dyn ZFCPClient + Send + 'static>>,
|
|
}
|
|
|
|
impl Starter {
|
|
pub fn new(
|
|
events: event::Sender,
|
|
progress: Handler<progress::Service>,
|
|
issues: Handler<issue::Service>,
|
|
connection: zbus::Connection,
|
|
) -> Self {
|
|
Self {
|
|
events,
|
|
progress,
|
|
issues,
|
|
connection,
|
|
dasd: None,
|
|
zfcp: None,
|
|
}
|
|
}
|
|
|
|
pub fn with_dasd(mut self, client: impl DASDClient + Send + 'static) -> Self {
|
|
self.dasd = Some(Box::new(client));
|
|
self
|
|
}
|
|
|
|
pub fn with_zfcp(mut self, client: impl ZFCPClient + Send + 'static) -> Self {
|
|
self.zfcp = Some(Box::new(client));
|
|
self
|
|
}
|
|
|
|
pub async fn start(self) -> Result<Handler<Service>, Error> {
|
|
// Create storage_client only if needed.
|
|
let (service, storage_client) = match (self.dasd, self.zfcp) {
|
|
(Some(dasd), Some(zfcp)) => {
|
|
let service = Service { dasd, zfcp };
|
|
(service, None)
|
|
}
|
|
(dasd_opt, zfcp_opt) => {
|
|
let storage_client = storage_client::service::Starter::new(self.connection.clone())
|
|
.start()
|
|
.await?;
|
|
|
|
let dasd =
|
|
dasd_opt.unwrap_or_else(|| Box::new(dasd::Client::new(storage_client.clone())));
|
|
|
|
let zfcp =
|
|
zfcp_opt.unwrap_or_else(|| Box::new(zfcp::Client::new(storage_client.clone())));
|
|
|
|
let service = Service { dasd, zfcp };
|
|
|
|
(service, Some(storage_client))
|
|
}
|
|
};
|
|
|
|
let handler = actor::spawn(service);
|
|
|
|
let dasd_monitor = dasd::Monitor::new(
|
|
self.progress.clone(),
|
|
self.events.clone(),
|
|
self.connection.clone(),
|
|
);
|
|
dasd::monitor::spawn(dasd_monitor)?;
|
|
|
|
// FIXME: allow mocking storage_client instead of preventing its creation during tests.
|
|
if let Some(storage_client) = storage_client {
|
|
let zfcp_monitor = zfcp::Monitor::new(
|
|
self.progress,
|
|
self.issues,
|
|
self.events,
|
|
self.connection,
|
|
storage_client.clone(),
|
|
);
|
|
zfcp::monitor::spawn(zfcp_monitor)?;
|
|
}
|
|
|
|
Ok(handler)
|
|
}
|
|
}
|
|
|
|
pub struct Service {
|
|
dasd: Box<dyn DASDClient + Send + 'static>,
|
|
zfcp: Box<dyn ZFCPClient + Send + 'static>,
|
|
}
|
|
|
|
impl Service {
|
|
pub fn starter(
|
|
events: event::Sender,
|
|
progress: Handler<progress::Service>,
|
|
issues: Handler<issue::Service>,
|
|
connection: zbus::Connection,
|
|
) -> Starter {
|
|
Starter::new(events, progress, issues, connection)
|
|
}
|
|
}
|
|
|
|
impl Actor for Service {
|
|
type Error = Error;
|
|
}
|
|
|
|
#[async_trait]
|
|
impl MessageHandler<message::ProbeDASD> for Service {
|
|
async fn handle(&mut self, _message: message::ProbeDASD) -> Result<(), Error> {
|
|
self.dasd.probe().await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl MessageHandler<message::ProbeZFCP> for Service {
|
|
async fn handle(&mut self, _message: message::ProbeZFCP) -> Result<(), Error> {
|
|
self.zfcp.probe().await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl MessageHandler<message::GetSystem> for Service {
|
|
async fn handle(&mut self, _message: message::GetSystem) -> Result<SystemInfo, Error> {
|
|
let dasd = self.dasd.get_system().await?;
|
|
let zfcp = self.zfcp.get_system().await?;
|
|
Ok(SystemInfo { dasd, zfcp })
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl MessageHandler<message::GetConfig> for Service {
|
|
async fn handle(&mut self, _message: message::GetConfig) -> Result<Config, Error> {
|
|
let dasd = self.dasd.get_config().await?;
|
|
let zfcp = self.zfcp.get_config().await?;
|
|
Ok(Config { dasd, zfcp })
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl MessageHandler<message::SetZFCPConfig> for Service {
|
|
async fn handle(
|
|
&mut self,
|
|
message: message::SetZFCPConfig,
|
|
) -> Result<BoxFuture<Result<(), Error>>, Error> {
|
|
let rx = self.zfcp.set_config(message.config).await?;
|
|
Ok(Box::pin(async move { rx.await.map_err(Error::from) }))
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl MessageHandler<message::SetDASDConfig> for Service {
|
|
async fn handle(
|
|
&mut self,
|
|
message: message::SetDASDConfig,
|
|
) -> Result<BoxFuture<Result<(), Error>>, Error> {
|
|
let rx = self.dasd.set_config(message.config).await?;
|
|
Ok(Box::pin(async move { rx.await.map_err(Error::from) }))
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl MessageHandler<message::SetLocale> for Service {
|
|
async fn handle(&mut self, _message: message::SetLocale) -> Result<(), Error> {
|
|
self.zfcp.probe().await?;
|
|
Ok(())
|
|
}
|
|
}
|