| #include "baremetal_callback.h" |
| |
| #include <unistd.h> |
| |
| |
| #include <cstdlib> |
| #include <filesystem> // NOLINT |
| #include <fstream> |
| #include <sstream> |
| #include <string> |
| #include <system_error> // NOLINT |
| #include <thread> |
| |
| #include "absl/log/log.h" |
| #include "grpcpp/server_context.h" |
| #include "grpcpp/support/status.h" |
| |
| namespace blobs { |
| |
| grpc::Status BaremetalTransferServiceImpl::BmModeTransfer( |
| [[maybe_unused]] grpc::ServerContext* context, |
| [[maybe_unused]] const phosphor::baremetal::BmModeRequest* request, |
| phosphor::baremetal::BmModeResponse* response) { |
| /* |
| enum BmMode { |
| BMMODE_UNKNOWN = 0; |
| BMMODE_NON_BM = 1; |
| BMMODE_BM = 2; |
| BMMODE_STEADY_STATE = 3; |
| } |
| */ |
| std::error_code ec; |
| |
| if (std::filesystem::exists( |
| std::string(bmDriveCleaningDoneAckFlagPath) + instanceString, ec)) { |
| LOG(INFO) << "We acked cleaning done and must be in BM mode"; |
| response->set_bm_mode(phosphor::baremetal::BmMode::BMMODE_BM); |
| return grpc::Status::OK; |
| } |
| |
| if (std::filesystem::exists( |
| std::string(bmDriveCleaningDoneFlagPath) + instanceString, ec)) { |
| std::filesystem::rename( |
| std::string(bmDriveCleaningDoneFlagPath) + instanceString, |
| std::string(bmDriveCleaningDoneAckFlagPath) + instanceString, ec); |
| LOG(INFO) << "We just finished cleaning and must be in BM mode"; |
| response->set_bm_mode(phosphor::baremetal::BmMode::BMMODE_BM); |
| return grpc::Status::OK; |
| } |
| |
| if (std::filesystem::exists(std::string(bmSignalPath), ec)) { |
| if (!std::filesystem::exists( |
| std::string(bmDriveCleaningFlagPath) + instanceString, ec)) { |
| std::ofstream file(std::string(bmDriveCleaningFlagPath) + instanceString); |
| } |
| |
| LOG(INFO) << "We must be in BM cleaning mode"; |
| response->set_bm_mode(phosphor::baremetal::BmMode::BMMODE_STEADY_STATE); |
| return grpc::Status::OK; |
| } |
| |
| // Set default response |
| LOG(INFO) << "We must not be in BM mode"; |
| response->set_bm_mode(phosphor::baremetal::BmMode::BMMODE_NON_BM); |
| return grpc::Status::OK; |
| } |
| |
| grpc::Status BaremetalTransferServiceImpl::LinuxBootDone( |
| [[maybe_unused]] grpc::ServerContext* context, |
| [[maybe_unused]] const phosphor::baremetal::LinuxBootDoneRequest* request, |
| [[maybe_unused]] phosphor::baremetal::LinuxBootDoneResponse* response) { |
| LOG(INFO) << "LinuxBootDone on this instance number: " << instanceNumber; |
| |
| // Asynchronously start the systemd targets that will disable communication |
| // with the host. |
| std::thread systemd_thread([this]() { |
| std::stringstream bm_prep_stream; |
| // Use instanceString instead of instanceNumber because the instanceString |
| // variables are "1" and "2", whereas instanceNumber is 0 and 1 |
| bm_prep_stream << "gbmc-bare-metal-prep@" << this->instanceString |
| << ".target"; |
| std::string bm_prep_target = bm_prep_stream.str(); |
| |
| // Start the bare metal prep target. This can be used to monitor the |
| // ethernet connection to the host and wait until the CN shuts down the PCIe |
| // connection. |
| // Note: Use "systemctl restart" in case the target was already started on a |
| // previous CN boot. |
| int ret = system(("systemctl restart " + bm_prep_target).c_str()); |
| if (ret != 0) { |
| LOG(ERROR) << "Failed to start target: " << bm_prep_target |
| << " error: " << ret; |
| } else { |
| LOG(INFO) << "Successfully started target: " << bm_prep_target; |
| } |
| |
| // Now we'll start the gbmc-bare-metal-active target. |
| std::stringstream bm_active_stream; |
| bm_active_stream << "gbmc-bare-metal-active@" << this->instanceString |
| << ".target"; |
| std::string bm_active_target = bm_active_stream.str(); |
| ret = system(("systemctl start " + bm_active_target).c_str()); |
| if (ret != 0) { |
| LOG(ERROR) << "Failed to start target: " << bm_active_target |
| << " error: " << ret; |
| } else { |
| LOG(INFO) << "Successfully started target: " << bm_active_target; |
| } |
| }); |
| systemd_thread.detach(); |
| |
| return grpc::Status::OK; |
| } |
| |
| grpc::Status BaremetalTransferServiceImpl::BMInstancePropertiesTransfer( |
| [[maybe_unused]] grpc::ServerContext* context, |
| [[maybe_unused]] const phosphor::baremetal:: |
| BMInstancePropertiesTransferRequest* request, |
| phosphor::baremetal::BMInstancePropertiesTransferResponse* response) { |
| LOG(INFO) << "BMInstancePropertiesTransfer on this instance number: " |
| << instanceNumber; |
| |
| response->set_asset_tag(readBMInstanceFromFile( |
| std::string(bmInstanceBasePath) + "asset-tag" + instanceString)); |
| response->set_board_serial_number( |
| readBMInstanceFromFile(std::string(bmInstanceBasePath) + |
| "board-serial-number" + instanceString)); |
| response->set_family(readBMInstanceFromFile(std::string(bmInstanceBasePath) + |
| "family" + instanceString)); |
| response->set_product_name(readBMInstanceFromFile( |
| std::string(bmInstanceBasePath) + "product-name" + instanceString)); |
| response->set_sku(readBMInstanceFromFile(std::string(bmInstanceBasePath) + |
| "sku" + instanceString)); |
| response->set_system_serial_number( |
| readBMInstanceFromFile(std::string(bmInstanceBasePath) + |
| "system-serial-number" + instanceString)); |
| response->set_uuid(readBMInstanceFromFile(std::string(bmInstanceBasePath) + |
| "uuid" + instanceString)); |
| return grpc::Status::OK; |
| } |
| |
| std::string BaremetalTransferServiceImpl::readBMInstanceFromFile( |
| const std::string& bmInstancePath) { |
| // If the path doesn't exist, set it to an empty string |
| if (!std::filesystem::exists(bmInstancePath)) { |
| return {}; |
| } |
| |
| std::ifstream ifs; |
| ifs.exceptions(std::ifstream::failbit); |
| std::string property; |
| try { |
| ifs.open(bmInstancePath); |
| std::getline(ifs, property); |
| } catch (const std::ios_base::failure& fail) { |
| return {}; |
| } |
| return property; |
| } |
| |
| } // namespace blobs |