日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt开发之路——基于RedfishAPI的服务器管理小应用

發(fā)布時(shí)間:2023/12/31 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt开发之路——基于RedfishAPI的服务器管理小应用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


基于Redfish的服務(wù)器管理小應(yīng)用

  • 前言
    • 關(guān)于ipmi
    • 關(guān)于Redfish
    • 關(guān)于RedfishAPI
  • 效果
    • 開發(fā)環(huán)境
    • 功能介紹
  • 技術(shù)
    • Qt樣式表
    • 信號(hào)槽
    • treeWidget的使用
    • https請求及解析
    • QSlite數(shù)據(jù)庫的使用
  • 參考

前言

本文介紹了近期完成的一個(gè)小項(xiàng)目——基于Redfish的服務(wù)器管理小應(yīng)用。一方面記錄一下自己的開發(fā)經(jīng)歷;另一方面本項(xiàng)目適用于準(zhǔn)備學(xué)習(xí)樣式表,信號(hào)槽,treeWidget,https請求,SQlite數(shù)據(jù)庫的人。代碼在最下方。

注:公司內(nèi)部網(wǎng)絡(luò)才可以訪問redfish接口,項(xiàng)目的網(wǎng)絡(luò)請求無法發(fā)送成功,所以關(guān)于https請求部分僅供參考,也可以參看Qt開發(fā)之路——Json解析過程中遇到的readAll()清除內(nèi)存緩沖區(qū)問題~

關(guān)于ipmi

IMPI(智能平臺(tái)管理接口)是一種嵌入式功能,同時(shí)也是工業(yè)標(biāo)準(zhǔn),由英特爾與戴爾、惠普和NEC合作開發(fā),可實(shí)現(xiàn)對服務(wù)器的遠(yuǎn)程控制。但是這種規(guī)范也有它的局限性,層出不窮的安全問題使得它自從2015年更新2.0后沒有再翻新,與此同時(shí)Redfish興起。

關(guān)于Redfish

Redfish是由分布式管理任務(wù)組(DMTF)發(fā)布的開放式行業(yè)標(biāo)準(zhǔn)規(guī)范,旨在對平臺(tái)硬件進(jìn)行現(xiàn)代化和安全的管理,是一種管理標(biāo)準(zhǔn),在超媒體RESTful接口中使用數(shù)據(jù)模型表示。它是一個(gè)超媒體API,所以它能夠通過一個(gè)一致的接口來表示各種實(shí)現(xiàn)。它有管理數(shù)據(jù)中心資源、處理事件、長期任務(wù)和發(fā)現(xiàn)的機(jī)制。初識(shí)Redfish

關(guān)于RedfishAPI

RedfishAPI代表了一種新的編程風(fēng)格,它能夠以一致的方式管理從超級(jí)規(guī)模到刀片服務(wù)器再到獨(dú)立服務(wù)器的系統(tǒng)。

對于背景可以移步https://blog.csdn.net/asmartkiller/article/details/106558952作更細(xì)致的了解。

效果

開發(fā)環(huán)境

應(yīng)用:Qt Creator 4.11.1(Community)
開發(fā)環(huán)境:MinGW_32_bit
數(shù)據(jù)庫:SQlite

功能介紹

添加服務(wù)器:

初始化:刪除所有服務(wù)器
幫助:簡單顯示服務(wù)器小助手的功能
右鍵刷新告警及開關(guān)機(jī)狀態(tài)信息(再次請求系統(tǒng)信息和告警信息,即兩個(gè)get請求):

右鍵刪除服務(wù)器

技術(shù)

1、Qt樣式表,信號(hào)槽
2、通過treewidget組件顯示數(shù)據(jù)。
3、通過解析https請求到的JSON數(shù)據(jù)獲取相對應(yīng)的特征信息。
4、將數(shù)據(jù)存儲(chǔ)在Qt自帶的SQlite數(shù)據(jù)庫中,方便讀取和刪除。

Qt樣式表

因?yàn)槌绦虮容^小,且界面不多,所以樣式表直接在設(shè)計(jì)器里實(shí)現(xiàn)的。

比如存儲(chǔ)按鈕的點(diǎn)擊狀態(tài)

QPushButton#save{ border-style:outset; font: 75 16pt "宋體"; font-weight:bold; color:rgb(255, 170, 0); background-color:rgba(225, 225, 225, 0); }QPushButton#save:hover{ background-color:rgba(225, 225, 225,200); }QPushButton#save:pressed{ background-color:rgba(225, 225, 225, 200); }

信號(hào)槽

為了便于統(tǒng)一管理,將信號(hào)和槽寫在main函數(shù)中。主要用于界面之間的切換和值傳遞。

/* + 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的所有數(shù)據(jù)

//delete the treewidget for uiui->treeWidget->clear();

https請求及解析

https請求:QNetworkRequest、QNetworkAccessManager、QNetworkReply、QEventLoop

JSON解析:QJsonDocument、QJsonParseError、QJsonObject、QJsonArray、QJsonValue

主要涉及到對三種形式JSON數(shù)據(jù)的解析。涉及到3條url,這里記為url1,url2,url3。首先獲取token,然后根據(jù)token和url2發(fā)送get請求先后獲取產(chǎn)品名稱,開關(guān)機(jī)狀態(tài),健康狀態(tài)以及uuid。通過url3和token獲取服務(wù)器告警信息。
url1及用戶名密碼發(fā)送post請求獲取token:

QString AddId::postToken(QString id) {// new request objectQNetworkRequest request;// ready for sending https requestQSslConfiguration config;QSslConfiguration conf = request.sslConfiguration();conf.setPeerVerifyMode(QSslSocket::VerifyNone);conf.setProtocol(QSsl::TlsV1SslV3);request.setSslConfiguration(conf);request.setUrl(QUrl("https://www.baidu.com"));request.setUrl(QUrl(id));request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));//set raw header of requestrequest.setRawHeader("Content-Type", "application/json");//check supported agreementqDebug()<< manager->supportedSchemes();//("ftp", "file", "qrc", "http", "https", "data")//obtain form data——username and passwordQString submitMsg = QString(R"({"UserName": "%1","Password": "%2"})").arg(ui->lineEdit_2->text()).arg(ui->lineEdit_3->text());QNetworkReply *reply=manager->post(request,submitMsg.toUtf8());//open a local event loop, then wait reply but do not stop thread(significant)QEventLoop eventLoop;connect(manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);eventLoop.exec();/* for \"X-Auth-Token\":analysis json data*/QString token = analysisSessionsJson(reply);return token;

得到如下形式的JSON數(shù)據(jù):

{"@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}} }

解析獲取認(rèn)證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發(fā)送get請求獲取系統(tǒng)信息:

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數(shù)據(jù):

{"@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發(fā)送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數(shù)據(jù):

{"@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的數(shù)量和 不等于ok(嚴(yán)重告警)的數(shù)量。

/*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數(shù)據(jù)庫的使用

QSqlDatabase、QSqlQuery、QSqlError、QSqlTableModel

Qt開發(fā)之路——SQlite的使用(簡單粗暴)

github:https://github.com/hqy7777/SMS-Based-On-Redfish-Qt

參考

Qt開發(fā)之路——Json解析過程中遇到的readAll()清除內(nèi)存緩沖區(qū)問題
Qt開發(fā)之路——SQlite的使用(簡單粗暴)

歡迎討論交流~

總結(jié)

以上是生活随笔為你收集整理的Qt开发之路——基于RedfishAPI的服务器管理小应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。