77
88app = Flask (__name__ )
99
10- ip_address = os .getenv ("IP_ADDRESS " , "192.168.0.120" )
10+ idrac_host = os .getenv ("IDRAC_HOST " , "192.168.0.120" )
1111username = os .getenv ("IDRAC_USERNAME" , "root" )
1212password = os .getenv ("IDRAC_PASSWORD" , "calvin" )
13+ playwright_working_dir = os .getenv ("PLAYWRIGHT_WORKING_DIR" , "../playwright-boostrap/" ) # noqa: E501
14+ PWDEBUG = os .getenv ("PWDEBUG" , False )
15+ playwright_headed = "--headed" if "PWDEBUG" in os .environ else ''
1316
1417IDRAC_SCRIPTS_BASE_PATH = os .getenv (
1518 "IDRAC_SCRIPTS_BASE_PATH" , "./iDRAC-Redfish-Scripting/Redfish Python/"
@@ -29,18 +32,25 @@ def index():
2932
3033
3134def execute_redfish_command (action ):
32- if action == "VerifyiDRACAccess" :
33- url = f"https://{ ip_address } /redfish/v1/Systems/"
34- headers = {"Content-Type" : "application/json" }
35- payload = {"ResetType" : "ForceRestart" }
36- auth = (username , password )
37- req = requests .get (
38- url , headers = headers , json = payload , auth = auth , verify = False
39- ) # noqa: E501
40- return api_response (req )
35+ if action == "Bootstrap" :
36+ VerifyiDRACAccess ()
37+ ForceOff ()
38+ sleepSecconds = 10
39+ print (f"Sleeping for { sleepSecconds } " )
40+ iDRACSetVirtualTerminalHTML5 ()
41+ UnmountISO ()
42+ UnmountISO ()
43+ MountISO ()
44+ MountISO ()
45+ GetPowerState ()
46+ from time import sleep
47+ sleepSecconds = 10
48+ print (f"Sleeping for { sleepSecconds } " )
49+ sleep (sleepSecconds )
50+ return PowerOn ()
4151
4252 if action == "ForceRestart" :
43- url = f"https://{ ip_address } /redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # noqa: E501
53+ url = f"https://{ idrac_host } /redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # noqa: E501
4454 headers = {"Content-Type" : "application/json" }
4555 payload = {"ResetType" : "ForceRestart" }
4656 auth = (username , password )
@@ -50,57 +60,10 @@ def execute_redfish_command(action):
5060 ) # noqa: E501
5161 return api_response (req )
5262
53- if action == "MountiPXE" :
54- command = (
55- f'curl -v -H "Content-Type: application/json" -X POST -u { username } :{ password } ' # noqa: E501
56- f"-k https://{ ip_address } /redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia/CD/Actions/VirtualMedia.InsertMedia " # noqa: E501
57- f'-d \' {{"Image": "http://138.201.59.208/sites/default/files/ipxe.iso"}}\' ' # noqa: E501
58- )
59-
60- # URL
61- url = f"https://{ ip_address } /redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia/CD/Actions/VirtualMedia.InsertMedia" # noqa: E501
62-
63- # Headers
64- headers = {"Content-Type" : "application/json" }
65-
66- # Data
67- data = {"Image" : "http://138.201.59.208/sites/default/files/ipxe.iso" }
68-
69- # Making the request
70- req = requests .post (
71- url ,
72- headers = headers ,
73- json = data ,
74- auth = HTTPBasicAuth (username , password ),
75- verify = False ,
76- )
77- return api_response (req )
78-
79- if action == "UnMountiPXE" :
80-
81- # URL
82- url = f"https://{ ip_address } /redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia/CD/Actions/VirtualMedia.EjectMedia" # noqa: E501
83-
84- # Headers
85- headers = {"Content-Type" : "application/json" }
86-
87- # Data
88- data = {}
89-
90- # Making the request
91- req = requests .post (
92- url ,
93- headers = headers ,
94- json = data ,
95- auth = HTTPBasicAuth (username , password ),
96- verify = False ,
97- )
98- return api_response (req )
99-
10063 if action == "GetOnetimeBootValue" :
10164
10265 # URL
103- url = f"https://{ ip_address } /redfish/v1/Systems/System.Embedded.1"
66+ url = f"https://{ idrac_host } /redfish/v1/Systems/System.Embedded.1"
10467
10568 # Making the request
10669 req = requests .get (
@@ -110,72 +73,49 @@ def execute_redfish_command(action):
11073 )
11174 return api_response (req )
11275
113- if action == "GetPowerState" :
114- # URL
115- url = f"https://{ ip_address } /redfish/v1/Systems/System.Embedded.1"
116-
117- # Making the request
118- req = requests .get (
119- url ,
120- auth = HTTPBasicAuth (username , password ),
121- verify = False ,
122- )
123- if req .status_code == 200 :
124- response_text = (
125- f"Current server power state: { req .json ()['PowerState' ]} " # noqa: E501
126- )
127- req = SimpleNamespace ()
128- req .status_code = 200
129- req .text = response_text
130- return api_response (req )
131-
13276 if action == "ChangeBiosBootOrderREDFISH" :
133- command = f"python { IDRAC_SCRIPTS_BASE_PATH } ChangeBiosBootOrderREDFISH.py -ip { ip_address } -u { username } -p { password } --get" # noqa: E501
77+ command = f"python { IDRAC_SCRIPTS_BASE_PATH } ChangeBiosBootOrderREDFISH.py -ip { idrac_host } -u { username } -p { password } --get" # noqa: E501
13478 result = subprocess .run (command , capture_output = True , shell = True )
13579
136- if action == "On" :
137- # URL
138- url = f"https://{ ip_address } /redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # noqa: E501
139-
140- # Headers
141- headers = {"Content-Type" : "application/json" }
142-
143- # Data
144- data = {"ResetType" : "On" }
145-
146- # Making the request
147- req = requests .post (
148- url ,
149- headers = headers ,
150- json = data ,
151- auth = HTTPBasicAuth (username , password ),
152- verify = False ,
153- )
154- return api_response (req )
80+ else :
81+ command = f"python { IDRAC_SCRIPTS_BASE_PATH } GetSetPowerStateREDFISH.py -ip { idrac_host } -u { username } -p { password } --set { action } " # noqa: E501
82+ result = subprocess .run (command , capture_output = True , shell = True )
83+ return (
84+ jsonify (
85+ {
86+ "output" : result .stdout .decode ("utf-8" ),
87+ "error" : result .stderr .decode ("utf-8" ),
88+ }
89+ ),
90+ result .returncode ,
91+ )
15592
156- if action == "ForceOff" :
157- # URL
158- url = f"https://{ ip_address } /redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # noqa: E501
15993
160- # Headers
161- headers = {"Content-Type" : "application/json" }
94+ @app .route ("/api/v1/Bootstrap" , methods = ["POST" ])
95+ def bootstrap ():
96+ return execute_redfish_command ("Bootstrap" )
16297
163- # Data
164- data = {"ResetType" : "ForceOff" }
16598
166- # Making the request
167- req = requests .post (
168- url ,
169- headers = headers ,
170- json = data ,
171- auth = HTTPBasicAuth (username , password ),
172- verify = False ,
173- )
174- return api_response (req )
175-
176- else :
177- command = f"python { IDRAC_SCRIPTS_BASE_PATH } GetSetPowerStateREDFISH.py -ip { ip_address } -u { username } -p { password } --set { action } " # noqa: E501
178- result = subprocess .run (command , capture_output = True , shell = True )
99+ @app .route ("/api/v1/VerifyiDRACAccess" , methods = ["POST" ])
100+ def VerifyiDRACAccess ():
101+ url = f"https://{ idrac_host } /redfish/v1/Systems/"
102+ headers = {"Content-Type" : "application/json" }
103+ payload = {"ResetType" : "ForceRestart" }
104+ auth = (username , password )
105+ req = requests .get (
106+ url , headers = headers , json = payload , auth = auth , verify = False
107+ ) # noqa: E501
108+ return api_response (req )
109+
110+
111+ @app .route ("/api/v1/iDRACSetVirtualTerminalHTML5" , methods = ["POST" ])
112+ def iDRACSetVirtualTerminalHTML5 ():
113+ command = (
114+ f"IDRAC_HOST=http://{ idrac_host } IDRAC_USERNAME={ username } "
115+ f"IDRAC_PASSWORD={ password } npx playwright test scripts/iDRAC-set-virtual-terminal-html5.spec.ts " # noqa: E501
116+ f" { playwright_headed } "
117+ )
118+ result = subprocess .run (command , cwd = playwright_working_dir , env = os .environ , capture_output = True , shell = True ) # noqa: E501
179119 return (
180120 jsonify (
181121 {
@@ -187,19 +127,50 @@ def execute_redfish_command(action):
187127 )
188128
189129
190- @app .route ("/api/v1/VerifyiDRACAccess" , methods = ["POST" ])
191- def verify_idrac_access ():
192- return execute_redfish_command ("VerifyiDRACAccess" )
130+ @app .route ("/api/v1/PowerOn" , methods = ["POST" ])
131+ def PowerOn ():
132+ print ("PowerOn" )
133+ # URL
134+ url = f"https://{ idrac_host } /redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # noqa: E501
193135
136+ # Headers
137+ headers = {"Content-Type" : "application/json" }
194138
195- @app .route ("/api/v1/On" , methods = ["POST" ])
196- def set_power_on ():
197- return execute_redfish_command ("On" )
139+ # Data
140+ data = {"ResetType" : "On" }
141+
142+ # Making the request
143+ req = requests .post (
144+ url ,
145+ headers = headers ,
146+ json = data ,
147+ auth = HTTPBasicAuth (username , password ),
148+ verify = False ,
149+ )
150+ return api_response (req )
198151
199152
200153@app .route ("/api/v1/ForceOff" , methods = ["POST" ])
201- def set_power_off ():
202- return execute_redfish_command ("ForceOff" )
154+ def ForceOff ():
155+ print ("ForceOff" )
156+ # URL
157+ url = f"https://{ idrac_host } /redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # noqa: E501
158+
159+ # Headers
160+ headers = {"Content-Type" : "application/json" }
161+
162+ # Data
163+ data = {"ResetType" : "ForceOff" }
164+
165+ # Making the request
166+ req = requests .post (
167+ url ,
168+ headers = headers ,
169+ json = data ,
170+ auth = HTTPBasicAuth (username , password ),
171+ verify = False ,
172+ )
173+ return api_response (req )
203174
204175
205176@app .route ("/api/v1/ForceRestart" , methods = ["POST" ])
@@ -213,23 +184,86 @@ def set_power_graceful_shutdown():
213184
214185
215186@app .route ("/api/v1/GetPowerState" , methods = ["POST" ])
216- def get_power_state ():
217- return execute_redfish_command ("GetPowerState" )
187+ def GetPowerState ():
188+ print ("GetPowerState" )
189+ # URL
190+ url = f"https://{ idrac_host } /redfish/v1/Systems/System.Embedded.1"
191+
192+ # Making the request
193+ req = requests .get (
194+ url ,
195+ auth = HTTPBasicAuth (username , password ),
196+ verify = False ,
197+ )
198+ if req .status_code == 200 :
199+ response_text = (
200+ f"Current server power state: { req .json ()['PowerState' ]} " # noqa: E501
201+ )
202+ req = SimpleNamespace ()
203+ req .status_code = 200
204+ req .text = response_text
205+ return api_response (req )
218206
219207
220208@app .route ("/api/v1/ChangeBiosBootOrderREDFISH" , methods = ["POST" ])
221209def get_bios_boot_order ():
222210 return execute_redfish_command ("ChangeBiosBootOrderREDFISH" )
223211
224212
225- @app .route ("/api/v1/MountiPXE" , methods = ["POST" ])
226- def mount_iPXE_iso ():
227- return execute_redfish_command ("MountiPXE" )
213+ @app .route ("/api/v1/MountISO" , methods = ["POST" ])
214+ def MountISO ():
215+ print ("MountISO" )
216+ # URL
217+ url = f"https://{ idrac_host } /redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia/CD/Actions/VirtualMedia.InsertMedia" # noqa: E501
218+
219+ # Headers
220+ headers = {"Content-Type" : "application/json" }
228221
222+ # Data
223+ data = {"Image" : "http://138.201.59.208/sites/default/files/ipxe.iso" }
224+
225+ # Making the request
226+ req = requests .post (
227+ url ,
228+ headers = headers ,
229+ json = data ,
230+ auth = HTTPBasicAuth (username , password ),
231+ verify = False ,
232+ )
233+
234+ if req .status_code == '500' :
235+ try :
236+ message = req .json ()['error' ]['@Message.ExtendedInfo' ][0 ]['Message' ] # noqa: E501
237+ if message == "The Virtual Media image server is already connected." : # noqa: E501
238+ print ("The Virtual Media image server is already connected." )
239+ else :
240+ breakpoint ()
241+ except Exception as e :
242+ print (e )
243+
244+ return api_response (req )
229245
230246@app .route ("/api/v1/UnmountISO" , methods = ["POST" ])
231- def unmount_iPXE_iso ():
232- return execute_redfish_command ("UnMountiPXE" )
247+ def UnmountISO ():
248+ print (UnmountISO )
249+ # URL
250+ url = f"https://{ idrac_host } /redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia/CD/Actions/VirtualMedia.EjectMedia" # noqa: E501
251+
252+ # Headers
253+ headers = {"Content-Type" : "application/json" }
254+
255+ # Data
256+ data = {}
257+
258+ # Making the request
259+ req = requests .post (
260+ url ,
261+ headers = headers ,
262+ json = data ,
263+ auth = HTTPBasicAuth (username , password ),
264+ verify = False ,
265+ )
266+ return api_response (req )
233267
234268
235269@app .route ("/api/v1/GetOnetimeBootValue" , methods = ["POST" ])
0 commit comments