Qt开发之路——基于RedfishAPI的服务器管理小应用
基于Redfish的服務器管理小應用
- 前言
- 關于ipmi
- 關于Redfish
- 關于RedfishAPI
- 效果
- 開發環境
- 功能介紹
- 技術
- Qt樣式表
- 信號槽
- treeWidget的使用
- https請求及解析
- QSlite數據庫的使用
- 參考
前言
本文介紹了近期完成的一個小項目——基于Redfish的服務器管理小應用。一方面記錄一下自己的開發經歷;另一方面本項目適用于準備學習樣式表,信號槽,treeWidget,https請求,SQlite數據庫的人。代碼在最下方。
注:公司內部網絡才可以訪問redfish接口,項目的網絡請求無法發送成功,所以關于https請求部分僅供參考,也可以參看Qt開發之路——Json解析過程中遇到的readAll()清除內存緩沖區問題~
關于ipmi
IMPI(智能平臺管理接口)是一種嵌入式功能,同時也是工業標準,由英特爾與戴爾、惠普和NEC合作開發,可實現對服務器的遠程控制。但是這種規范也有它的局限性,層出不窮的安全問題使得它自從2015年更新2.0后沒有再翻新,與此同時Redfish興起。
關于Redfish
Redfish是由分布式管理任務組(DMTF)發布的開放式行業標準規范,旨在對平臺硬件進行現代化和安全的管理,是一種管理標準,在超媒體RESTful接口中使用數據模型表示。它是一個超媒體API,所以它能夠通過一個一致的接口來表示各種實現。它有管理數據中心資源、處理事件、長期任務和發現的機制。初識Redfish
關于RedfishAPI
RedfishAPI代表了一種新的編程風格,它能夠以一致的方式管理從超級規模到刀片服務器再到獨立服務器的系統。
對于背景可以移步https://blog.csdn.net/asmartkiller/article/details/106558952作更細致的了解。
效果
開發環境
應用:Qt Creator 4.11.1(Community)
開發環境:MinGW_32_bit
數據庫:SQlite
功能介紹
添加服務器:
初始化:刪除所有服務器
幫助:簡單顯示服務器小助手的功能
右鍵刷新告警及開關機狀態信息(再次請求系統信息和告警信息,即兩個get請求):
右鍵刪除服務器
技術
1、Qt樣式表,信號槽
2、通過treewidget組件顯示數據。
3、通過解析https請求到的JSON數據獲取相對應的特征信息。
4、將數據存儲在Qt自帶的SQlite數據庫中,方便讀取和刪除。
Qt樣式表
因為程序比較小,且界面不多,所以樣式表直接在設計器里實現的。
比如存儲按鈕的點擊狀態
信號槽
為了便于統一管理,將信號和槽寫在main函數中。主要用于界面之間的切換和值傳遞。
/* + functionui from widget to addid for adding servers*/QObject::connect(w,SIGNAL(showAddId()),i,SLOT(receive_widget_addid()));/* save functionui from addid to widget for showing servers data*/QObject::connect(i,SIGNAL(showLabel(QString,QString,QString,QString,QString,QString)),w,SLOT(receive_save(QString,QString,QString,QString,QString,QString)));/* cancel functionui from addid to widget for showing widget*/QObject::connect(i,SIGNAL(showWidget()),w,SLOT(receive_addid_cancel()));/* show loading uiui from addid to loading for showing waiting process*/QObject::connect(i,SIGNAL(showLoading()),l,SLOT(receive_addid_loading()));/* close loading uiui from addid to loading for showing widget ui*/QObject::connect(i,SIGNAL(closeLoading()),l,SLOT(receive_addid_closeloading()));/* refresh realdataui from widget to addid for refreshing realdata——powerstate and serveritynum*/QObject::connect(w,SIGNAL(refresh_realtimedata(QString)),i,SLOT(receive_widget_refresh(QString)));/* refresh realdataui from addid to widget for sending realdata——powerstate and serveritynum*/QObject::connect(i,SIGNAL(send_realTimeData(QString,QString)),w,SLOT(receive_realTimeData(QString,QString)));treeWidget的使用
添加一行
QStringList strs;strs<<QString("******")<<QString("*********")<<QString(powerstate)<<QString(severity)<<QString("***************");//set the header to appropriate sizeQHeaderView *head=ui->treeWidget->header();head->setSectionResizeMode(QHeaderView::ResizeToContents);//add one line for treewidget,content is strsQTreeWidgetItem *strsroot = new QTreeWidgetItem(ui->treeWidget,strs);//set currentitemui->treeWidget->setCurrentItem(strsroot);刪除一行
QTreeWidgetItem *item = ui->treeWidget->currentItem(); delete(item);刪除treewidget的所有數據
//delete the treewidget for uiui->treeWidget->clear();https請求及解析
https請求:QNetworkRequest、QNetworkAccessManager、QNetworkReply、QEventLoop
JSON解析:QJsonDocument、QJsonParseError、QJsonObject、QJsonArray、QJsonValue
主要涉及到對三種形式JSON數據的解析。涉及到3條url,這里記為url1,url2,url3。首先獲取token,然后根據token和url2發送get請求先后獲取產品名稱,開關機狀態,健康狀態以及uuid。通過url3和token獲取服務器告警信息。
url1及用戶名密碼發送post請求獲取token:
得到如下形式的JSON數據:
{"@odata.context": "/redfish/v1/$metadata#Session.Session","@odata.id": "/redfish/v1/****/*********","@odata.type": "#Session.*****.Session","Id": "********","Name": "User Session","Description": "Manager User Session","UserName": "****","SessionType": "Redfish","Oem": {"BMC": {"LoginTime": "2021-01-04T11:30:51+08:00\n","ClientAddress": "****","ServerAddress": "id","SessionId": "*****","EnabledHttps": true,"Role": "Administrator","Location": "/redfish/v1/*****/*************","X-Auth-Token": "lhe6Gqi4Lz2CA7rx15vc0IRNh22iz4Vb","UserId": 2}} }解析獲取認證X-Token
/*analysis SessionsJson for token url1 */ QString AddId::analysisSessionsJson(QNetworkReply *reply){//judge if format of the json is rightif (reply->error() == QNetworkReply::NoError){QByteArray bytes = reply->readAll(); //read all bytesQJsonParseError jsonError_login;//switch to json documentQJsonDocument document = QJsonDocument::fromJson(bytes, &jsonError_login);//analysis Json errorif (document.isObject()){QJsonObject obj = document.object();if (obj.contains("Oem")){QJsonObject object_value = obj.value("Oem").toObject();if (object_value.contains("BMC")){QJsonObject object1_value = object_value.value("BMC").toObject();if(object1_value.contains("X-Auth-Token")){QString token_val = object1_value.value("X-Auth-Token").toString();return token_val;}}}}} }url2及token發送get請求獲取系統信息:
QStringList AddId::getCriticalMsg(QString url,QString token) {QNetworkRequest request;QSslConfiguration config;QSslConfiguration conf = request.sslConfiguration();conf.setPeerVerifyMode(QSslSocket::VerifyNone);conf.setProtocol(QSsl::TlsV1SslV3);request.setSslConfiguration(conf);request.setUrl(QUrl("https://www.baidu.com"));//set url and xAuthTokenrequest.setUrl(QUrl(url));request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");request.setRawHeader(QByteArray("X-Auth-Token"),QByteArray(token.toUtf8()));QNetworkReply *systeminfo = manager->get(request);//if no below three codes,will first run the latter code after QNetworkReply *systeminfo = manager->get(request);then to run replyQEventLoop eventLoop;connect(manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);eventLoop.exec();QStringList criticalstr = analysisSystemJson(systeminfo);return criticalstr; }得到如下形式的JSON數據:
{"@odata.context": "/redfish/v1/$metadata#ComputerSystem.ComputerSystem","@odata.id": "/redfish/v1/******","@odata.type": "#ComputerSystem.ComputerSystem","Id": "1","Name": "Computer System","Actions": {"ResetType@Redfish.AllowableValues": ["On","ForceOff","ForceRestart","GracefulShutdown","ForcePowerCycle","Nmi"],"target": "/redfish/v1/*******"},"AssetTag": "******","Manufacturer": "********","Model": "********","SerialNumber": "********","PartNumber": "********","HostingRole": "ApplicationServer","SystemType": "Physical","UUID": "4********","HostName": "********","PowerState": "On","PowerRestorePolicyTypes": "LastState","IndicatorLED": "Off","BIOSVersion": "********","Status": {"State": "Enabled","Health": "OK"} }解析得到Manufacturer,PowerState,UUID,Health
/*analysis processing*url2 for product name,state of on or off,warnings num,GUID*/ QStringList AddId::analysisSystemJson(QNetworkReply *sys){QStringList criticalstr;if (sys->error() == QNetworkReply::NoError){QByteArray bytes = sys->readAll();QJsonParseError jsonError_system;QJsonDocument document = QJsonDocument::fromJson(bytes, &jsonError_system);if (document.isObject()){QJsonObject obj = document.object();if (obj.contains("Manufacturer")) {QString manufacturer = obj.value("Manufacturer").toString();criticalstr.append(manufacturer);qDebug() << manufacturer;}if (obj.contains("PowerState")) {QString powerstate = obj.value("PowerState").toString();criticalstr.append(powerstate);qDebug() << powerstate;}if (obj.contains("UUID")) {QString uuid = obj.value("UUID").toString();criticalstr.append(uuid);qDebug() << uuid;}if (obj.contains("Status")){QJsonObject object_value = obj.value("Status").toObject();if (object_value.contains("Health")){QString health = object_value.value("Health").toString();criticalstr.append(health);qDebug() << health;}}}} }通過url3和token發送get請求獲取告警率:
QString AddId::getSeverityMsg(QString url,QString token) {QNetworkRequest request;QSslConfiguration config;QSslConfiguration conf = request.sslConfiguration();conf.setPeerVerifyMode(QSslSocket::VerifyNone);conf.setProtocol(QSsl::TlsV1SslV3);request.setSslConfiguration(conf);request.setUrl(QUrl("https://www.baidu.com"));//set url and xAuthTokenrequest.setUrl(QUrl(url));request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");request.setRawHeader(QByteArray("X-Auth-Token"),QByteArray(token.toUtf8()));QNetworkReply *logserverinfo = manager->get(request);//if no below three codes,will first run the latter code after QNetworkReply *systeminfo = manager->get(request);then to run replyQEventLoop eventLoop;connect(manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);eventLoop.exec();QString healthrate = analysisLogServerJson(logserverinfo);return healthrate; }得到如下形式的JSON數據:
{"@odata.context": "/redfish/v1/******","@odata.id": "redfish/v1/******","@odata.type": "#LogEntryCollection.LogEntryCollection","Description": "Collection of entries for this log service","Name": "Log Service Entries Collection","Members@odata.count": 24,"Members": [{"@odata.id": "/redfish/v1/******/24","Id": "24","Name": "Log Entry 24","EntryType": "******","SensorNumber": 186,"Created": "2021-01-04T07:14:12","EventTimestamp": "2021-01-04T07:14:12","Severity": "Ok","EntryCode": "Assert","SensorType": "******/Interconnect","Message": "******/Interconnect is connected"},{"@odata.id": "/redfish/v1/******","Id": "23","Name": "Log Entry 23","EntryType": "SEL","SensorNumber": 184,"Created": "2021-01-04T07:14:12","EventTimestamp": "2021-01-04T07:14:12","Severity": "Ok","EntryCode": "Assert","SensorType": "******/Interconnect","Message": "******/Interconnect is connected"},...........] }解析獲得Severity = ok的數量和 不等于ok(嚴重告警)的數量。
/*get request*https://id/redfish/v1/Systems for product name,state of on or off,warnings num,GUID*/ QString AddId::analysisLogServerJson(QNetworkReply *logserver){int serveritynum = 0;int healthnum = 0;qint32 logcount = 0;if (logserver->error() == QNetworkReply::NoError){QByteArray bytes = logserver->readAll();QJsonParseError jsonError_logserver;QJsonDocument document = QJsonDocument::fromJson(bytes, &jsonError_logserver);if (document.isObject()){QJsonObject obj = document.object();if (obj.contains("Members@odata.count")){//note that value for "Members@odata.count" is not a stringlogcount = obj.value("Members@odata.count").toInt();}if (obj.contains("Members")){QJsonValue members = obj.value("Members");//the value of members is a arrayif(members.isArray()){for(int i = 0;i< logcount;i++){QJsonObject members_obj = members.toArray().at(i).toObject();if(members_obj.contains("Severity")){QString status_value = members_obj.value("Severity").toString();if(!(status_value == "Ok")){serveritynum +=1;}else{healthnum +=1;}}}}}}}QSlite數據庫的使用
QSqlDatabase、QSqlQuery、QSqlError、QSqlTableModel
Qt開發之路——SQlite的使用(簡單粗暴)
github:https://github.com/hqy7777/SMS-Based-On-Redfish-Qt
參考
Qt開發之路——Json解析過程中遇到的readAll()清除內存緩沖區問題
Qt開發之路——SQlite的使用(簡單粗暴)
歡迎討論交流~
總結
以上是生活随笔為你收集整理的Qt开发之路——基于RedfishAPI的服务器管理小应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言正交表测试用例,测试用例设计之正交
- 下一篇: 使用SubSonic生成数据访问层步骤