1# _SoL.py 2# 3# openipmi GUI SoL handling 4# 5# Author: MontaVista Software, Inc. 6# Corey Minyard <minyard@mvista.com> 7# source@mvista.com 8# 9# Copyright 2006 MontaVista Software Inc. 10# 11# This program is free software; you can redistribute it and/or 12# modify it under the terms of the GNU Lesser General Public License 13# as published by the Free Software Foundation; either version 2 of 14# the License, or (at your option) any later version. 15# 16# 17# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 18# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 23# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 25# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 26# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28# You should have received a copy of the GNU Lesser General Public 29# License along with this program; if not, write to the Free 30# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 31# 32import OpenIPMI 33try: 34 import Tix 35except: 36 import tkinter 37 from tkinter import tix as Tix 38 39from openipmigui import gui_setdialog 40from openipmigui import gui_term 41from openipmigui import gui_errstr 42 43# Note in this file SoL refers to the main SoL object and sol refers 44# to the connection. 45 46class AckTimeoutSet: 47 def __init__(self, SoL): 48 self.SoL = SoL 49 gui_setdialog.SetDialog("Set Ack Timeout for SoL", 50 [ self.SoL.sol.get_ACK_timeout() ], 1, self, 51 [ "Value (in microseconds)"] ) 52 return 53 54 def do_on_close(self): 55 self.SoL = None 56 return 57 58 def ok(self, vals): 59 if (self.SoL.sol): 60 self.SoL.sol.set_ACK_timeout(int(vals[0])) 61 return 62 63 pass 64 65 66class AckRetriesSet: 67 def __init__(self, SoL): 68 self.SoL = SoL 69 gui_setdialog.SetDialog("Set Ack Retries for SoL", 70 [ self.SoL.sol.get_ACK_retries() ], 1, self, 71 [ "Value (in microseconds)"] ) 72 return 73 74 def do_on_close(self): 75 self.SoL = None 76 return 77 78 def ok(self, vals): 79 if (self.SoL.sol): 80 self.SoL.sol.set_ACK_retries(int(vals[0])) 81 return 82 83 pass 84 85 86class SolTerm(gui_term.Terminal): 87 def __init__(self, parent, SoL): 88 self.SoL = SoL 89 gui_term.Terminal.__init__(self, parent) 90 return 91 92 def HandleTerminalOutput(self, data): 93 self.SoL.HandleOutput(data); 94 return 95 96class SoL(Tix.Toplevel): 97 def __init__(self, ui, domain_id, cnum): 98 Tix.Toplevel.__init__(self) 99 self.ui = ui 100 self.cnum = cnum; 101 self.sol = None 102 domain_id.to_domain(self) 103 if (self.sol == None): 104 return 105 self.nack_count = 0 106 self.take_input = True 107 self.in_destroy = False 108 self.title("SoL for " + self.dname + " connection " 109 + str(self.cnum)) 110 111 mbar = Tix.Frame(self) 112 fileb = Tix.Menubutton(mbar, text="File", underline=0, takefocus=0) 113 filemenu = Tix.Menu(fileb, tearoff=0) 114 self.filemenu = filemenu 115 fileb["menu"] = filemenu 116 filemenu.add_command(label="Open", command=self.open) 117 filemenu.add_command(label="Close", command=self.close, 118 state="disabled") 119 filemenu.add_command(label="Force Close", command=self.forceclose, 120 state="disabled") 121 filemenu.add_command(label="Quit", command=self.quit) 122 123 ctrlb = Tix.Menubutton(mbar, text="Controls", underline=0, takefocus=0) 124 ctrlmenu = Tix.Menu(ctrlb, tearoff=0) 125 self.ctrlmenu = ctrlmenu 126 ctrlb["menu"] = ctrlmenu 127 128 self.acceptinput = Tix.BooleanVar() 129 self.acceptinput.set(True) 130 ctrlmenu.add_checkbutton(label="Accept Input", 131 variable=self.acceptinput, 132 command=self.AcceptInputToggle) 133 134 self.useenc = Tix.BooleanVar() 135 self.useenc.set(self.sol.get_use_encryption()) 136 ctrlmenu.add_checkbutton(label="Use Encryption", 137 variable=self.useenc, 138 command=self.UseEncToggle) 139 140 self.useauth = Tix.BooleanVar() 141 self.useauth.set(self.sol.get_use_authentication()) 142 ctrlmenu.add_checkbutton(label="Use Authentication", 143 variable=self.useauth, 144 command=self.UseAuthToggle) 145 146 self.deassert_on_connect = Tix.BooleanVar() 147 self.deassert_on_connect.set( 148 self.sol.get_deassert_CTS_DCD_DSR_on_connect()) 149 ctrlmenu.add_checkbutton(label="Deassert CTS/DCD/DSR on connect", 150 variable=self.deassert_on_connect, 151 command=self.DeassertOnConnectToggle) 152 153 self.ctsassertable = Tix.BooleanVar() 154 self.ctsassertable.set(True) 155 ctrlmenu.add_checkbutton(label="CTS Assertable", 156 variable=self.ctsassertable, 157 command=self.CTSAssertableToggle, 158 state="disabled") 159 160 self.dcd_dsr = Tix.BooleanVar() 161 self.dcd_dsr.set(True) 162 ctrlmenu.add_checkbutton(label="DCD/DSR Asserted", 163 variable=self.dcd_dsr, 164 command=self.DCDDSRToggle, 165 state="disabled") 166 167 self.ri = Tix.BooleanVar() 168 self.ri.set(False) 169 ctrlmenu.add_checkbutton(label="RI Asserted", 170 variable=self.ri, 171 command=self.RIToggle, 172 state="disabled") 173 174 ctrlmenu.add_command(label="Set Ack Timeout", 175 command=self.SetAckTimeout) 176 ctrlmenu.add_command(label="Set Ack Retries", 177 command=self.SetAckRetries) 178 ctrlmenu.add_command(label="Send Break", 179 command=self.SendBreak, state="disabled") 180 181 sermenu = Tix.Menu(ctrlmenu, tearoff=0) 182 ctrlmenu.add_cascade(label="Serial Rate", menu=sermenu) 183 self.servar = Tix.StringVar() 184 self.servar.set("default") 185 sermenu.add_radiobutton(label="Default", value="default", 186 variable=self.servar, command=self.SetRate) 187 sermenu.add_radiobutton(label="9600", value="9600", 188 variable=self.servar, command=self.SetRate) 189 sermenu.add_radiobutton(label="19200", value="19200", 190 variable=self.servar, command=self.SetRate) 191 sermenu.add_radiobutton(label="38400", value="38400", 192 variable=self.servar, command=self.SetRate) 193 sermenu.add_radiobutton(label="57600", value="57600", 194 variable=self.servar, command=self.SetRate) 195 sermenu.add_radiobutton(label="115200", value="115200", 196 variable=self.servar, command=self.SetRate) 197 198 serbehavemenu = Tix.Menu(ctrlmenu, tearoff=0) 199 ctrlmenu.add_cascade(label="Serial Alert Behavior", menu=serbehavemenu) 200 self.serbehave = Tix.StringVar() 201 self.serbehave.set("fail") 202 serbehavemenu.add_radiobutton(label="Serial Alerts Fail", value="fail", 203 variable=self.serbehave, 204 command=self.SetSerialAlerts) 205 serbehavemenu.add_radiobutton(label="Serial Alerts Deferred", 206 value="defer", 207 variable=self.serbehave, 208 command=self.SetSerialAlerts) 209 serbehavemenu.add_radiobutton(label="Serial Alerts Succeed", 210 value="succeed", 211 variable=self.serbehave, 212 command=self.SetSerialAlerts) 213 214 flushmenu = Tix.Menu(ctrlmenu, tearoff=0) 215 self.flushmenu = flushmenu 216 ctrlmenu.add_cascade(label="Queue Flush", menu=flushmenu) 217 fmenus = [ ] 218 flushmenu.add_command(label="Flush BMC Transmit Queue", 219 command=self.FlushBMCXmit, 220 state="disabled") 221 fmenus.append("Flush BMC Transmit Queue") 222 flushmenu.add_command(label="Flush BMC Receive Queue", 223 command=self.FlushBMCRecv, 224 state="disabled") 225 fmenus.append("Flush BMC Receive Queue") 226 flushmenu.add_command(label="Flush My Transmit Queue", 227 command=self.FlushMyXmit, 228 state="disabled") 229 fmenus.append("Flush My Transmit Queue") 230 flushmenu.add_command(label="Flush My Receive Queue", 231 command=self.FlushMyRecv, 232 state="disabled") 233 fmenus.append("Flush My Receive Queue") 234 flushmenu.add_command(label="Flush BMC Queues", 235 command=self.FlushBMC, 236 state="disabled") 237 fmenus.append("Flush BMC Queues") 238 flushmenu.add_command(label="Flush My Queues", 239 command=self.FlushMe, 240 state="disabled") 241 fmenus.append("Flush My Queues") 242 flushmenu.add_command(label="Flush All Queues", 243 command=self.FlushAll, 244 state="disabled") 245 fmenus.append("Flush All Queues") 246 self.fmenus = fmenus 247 248 mbar.pack(side=Tix.TOP, fill=Tix.X, expand=1) 249 fileb.pack(side=Tix.LEFT) 250 ctrlb.pack(side=Tix.LEFT) 251 252 self.term = SolTerm(self, self) 253 f = Tix.Frame(self) 254 f.pack(side=Tix.BOTTOM, fill=Tix.X, expand=1) 255 self.errstr = gui_errstr.ErrStr(f) 256 self.errstr.pack(side=Tix.LEFT, fill=Tix.X, expand=1) 257 self.statestr = gui_errstr.ErrStr(f) 258 self.statestr.pack(side=Tix.LEFT, fill=Tix.X, expand=1) 259 260 self.statestr.SetError(OpenIPMI.sol_state_string( 261 OpenIPMI.sol_state_closed)) 262 self.state = OpenIPMI.sol_state_closed 263 264 self.bind("<Destroy>", self.OnDestroy) 265 return 266 267 def OnDestroy(self, event): 268 self.in_destroy = True 269 if (self.sol != None): 270 self.sol.force_close() 271 self.sol = None 272 pass 273 return 274 275 def domain_cb(self, domain): 276 self.sol = domain.create_sol(self.cnum, self) 277 if (self.sol == None): 278 self.ui.ReportError("Unable to open SoL connection") 279 self.destroy() 280 return 281 self.dname = domain.get_name() 282 return 283 284 def HandleOutput(self, data): 285 self.sol.write(data) 286 return 287 288 def sol_connection_state_change(self, conn, state, err): 289 if (self.in_destroy): 290 return 291 if (err != 0): 292 self.errstr.SetError("Connection change: " 293 + OpenIPMI.sol_state_string(state) 294 + " " + OpenIPMI.get_error_string(err)) 295 pass 296 self.statestr.SetError(OpenIPMI.sol_state_string(state)) 297 if ((self.state != OpenIPMI.sol_state_closed) 298 and (state == OpenIPMI.sol_state_closed)): 299 self.filemenu.entryconfigure("Open", state="normal") 300 self.filemenu.entryconfigure("Close", state="disabled") 301 self.filemenu.entryconfigure("Force Close", state="disabled") 302 self.ctrlmenu.entryconfigure("Use Encryption", state="normal") 303 self.ctrlmenu.entryconfigure("Use Authentication", state="normal") 304 self.ctrlmenu.entryconfigure("Deassert CTS/DCD/DSR on connect", 305 state="normal") 306 self.ctrlmenu.entryconfigure("CTS Assertable", state="disabled") 307 self.ctrlmenu.entryconfigure("DCD/DSR Asserted", state="disabled") 308 self.ctrlmenu.entryconfigure("RI Asserted", state="disabled") 309 self.ctrlmenu.entryconfigure("Send Break", state="disabled") 310 for f in self.fmenus: 311 self.flushmenu.entryconfigure(f, state="disabled") 312 pass 313 pass 314 elif ((self.state == OpenIPMI.sol_state_closed) 315 and (state != OpenIPMI.sol_state_closed)): 316 self.filemenu.entryconfigure("Open", state="disabled") 317 self.filemenu.entryconfigure("Close", state="normal") 318 self.filemenu.entryconfigure("Force Close", state="normal") 319 self.ctrlmenu.entryconfigure("Use Encryption", state="disabled") 320 self.ctrlmenu.entryconfigure("Use Authentication", 321 state="disabled") 322 self.ctrlmenu.entryconfigure("Deassert CTS/DCD/DSR on connect", 323 state="disabled") 324 self.ctrlmenu.entryconfigure("CTS Assertable", state="normal") 325 self.ctrlmenu.entryconfigure("DCD/DSR Asserted", state="normal") 326 self.ctrlmenu.entryconfigure("RI Asserted", state="normal") 327 self.ctrlmenu.entryconfigure("Send Break", state="normal") 328 for f in self.fmenus: 329 self.flushmenu.entryconfigure(f, state="normal") 330 pass 331 pass 332 self.state = state 333 return 334 335 def open(self): 336 self.sol.open() 337 return 338 339 def close(self): 340 self.sol.close() 341 return 342 343 def forceclose(self): 344 self.sol.force_close() 345 return 346 347 def quit(self): 348 self.destroy() 349 return 350 351 def AcceptInputToggle(self): 352 if (self.acceptinput.get()): 353 self.take_input = True 354 for i in range(0, self.nack_count): 355 self.sol.release_nack(); 356 pass 357 self.nack_count = 0; 358 pass 359 else: 360 self.take_input = False 361 pass 362 return 363 364 def UseEncToggle(self): 365 self.sol.set_use_encryption(self.useenc.get()) 366 return 367 368 def UseAuthToggle(self): 369 self.sol.set_use_authentication(self.useauth.get()) 370 return 371 372 def DeassertOnConnectToggle(self): 373 self.sol.set_deassert_CTS_DCD_DSR_on_connect( 374 self.deassert_on_connect.get()) 375 return 376 377 def CTSAssertableToggle(self): 378 self.sol.set_CTS_assertable(self.ctsassertable.get()) 379 return 380 381 def DCDDSRToggle(self): 382 self.sol.set_DCD_DSR_asserted(self.dcd_dsr.get()) 383 return 384 385 def RIToggle(self): 386 self.sol.set_RI_asserted(self.ri.get()) 387 return 388 389 def SetAckTimeout(self): 390 AckTimeoutSet(self) 391 return 392 393 def SetAckRetries(self): 394 AckRetriesSet(self) 395 return 396 397 def SetRate(self): 398 val = self.servar.get() 399 if (val == "default"): 400 self.sol.set_bit_rate(OpenIPMI.SOL_BIT_RATE_DEFAULT) 401 elif (val == "9600"): 402 self.sol.set_bit_rate(OpenIPMI.SOL_BIT_RATE_9600) 403 elif (val == "19200"): 404 self.sol.set_bit_rate(OpenIPMI.SOL_BIT_RATE_19200) 405 elif (val == "38400"): 406 self.sol.set_bit_rate(OpenIPMI.SOL_BIT_RATE_38400) 407 elif (val == "57600"): 408 self.sol.set_bit_rate(OpenIPMI.SOL_BIT_RATE_57600) 409 elif (val == "115200"): 410 self.sol.set_bit_rate(OpenIPMI.SOL_BIT_RATE_115200) 411 pass 412 return 413 414 def SetSerialAlerts(self): 415 val = self.serbehave.get() 416 if (val == "fail"): 417 self.sol.set_shared_serial_alert_behavior( 418 OpenIPMI.sol_serial_alerts_fail) 419 elif (val == "deferred"): 420 self.sol.set_shared_serial_alert_behavior( 421 OpenIPMI.sol_serial_alerts_deferred) 422 elif (val == "succeed"): 423 self.sol.set_shared_serial_alert_behavior( 424 OpenIPMI.sol_serial_alerts_succeed) 425 return 426 427 def FlushBMCXmit(self): 428 self.sol.flush(OpenIPMI.SOL_BMC_TRANSMIT_QUEUE) 429 return 430 431 def FlushBMCRecv(self): 432 self.sol.flush(OpenIPMI.SOL_BMC_RECEIVE_QUEUE) 433 return 434 435 def FlushMyXmit(self): 436 self.sol.flush(OpenIPMI.SOL_MANAGEMENT_CONSOLE_TRANSMIT_QUEUE) 437 return 438 439 def FlushMyRecv(self): 440 self.sol.flush(OpenIPMI.SOL_MANAGEMENT_CONSOLE_RECEIVE_QUEUE) 441 return 442 443 def FlushBMC(self): 444 self.sol.flush(OpenIPMI.SOL_BMC_QUEUES) 445 return 446 447 def FlushMe(self): 448 self.sol.flush(OpenIPMI.SOL_MANAGEMENT_CONSOLE_QUEUES) 449 return 450 451 def FlushAll(self): 452 self.sol.flush(OpenIPMI.SOL_ALL_QUEUES) 453 return 454 455 def SendBreak(self): 456 self.sol.send_break() 457 return 458 459 def sol_data_received(self, conn, string): 460 if (not self.take_input): 461 self.nack_count += 1 462 return 1 463 try: 464 self.term.ProcessInput(string) 465 except Exception as e: 466 import sys 467 t, v, b = sys.exc_info() 468 sys.excepthook(t, v, b) 469 del b 470 pass 471 return 0 472 473 def sol_break_detected(self, conn): 474 self.errstr.SetError("Received break") 475 return 476 477 def sol_bmc_transmit_overrun(self, conn): 478 self.errstr.SetError("BMC Transmit Overrun") 479 return 480 481 pass 482