diff --git a/checkin_notes b/checkin_notes index 49dcbb354d..f2a8c4a5b9 100644 --- a/checkin_notes +++ b/checkin_notes @@ -414,3 +414,20 @@ Rom 12 Jan 2012 samples/vboxwrapper vbox.cpp, .h vboxwrapper.cpp, .h + +Rom 12 Jan 2012 + - client: Add plumbing to support passing the remote desktop + connection information to the manager + - MGR: Add a "Show VM Console" button for those tasks which + report a remote desktop port number. + + client/ + app.cpp, .h + app_control.cpp + clientgui/ + Events.h + MainDocument.cpp, .h + ViewWork.cpp, .h + lib/ + gui_rpc_client.h + gui_rpc_client_ops.cpp diff --git a/client/app.cpp b/client/app.cpp index 49b103b7dc..2a6a66e579 100644 --- a/client/app.cpp +++ b/client/app.cpp @@ -121,6 +121,7 @@ ACTIVE_TASK::ACTIVE_TASK() { overdue_checkpoint = false; last_deadline_miss_time = 0; strcpy(web_graphics_url, ""); + strcpy(remote_desktop_connection, ""); } // preempt this task; @@ -593,6 +594,12 @@ int ACTIVE_TASK::write_gui(MIOFILE& fout) { web_graphics_url ); } + if (strlen(remote_desktop_connection)) { + fout.printf( + " %s\n", + remote_desktop_connection + ); + } fout.printf("\n"); return 0; } diff --git a/client/app.h b/client/app.h index 7a5ddd7386..4a6c9ff5ec 100644 --- a/client/app.h +++ b/client/app.h @@ -151,6 +151,7 @@ struct ACTIVE_TASK { // (e.g. VMs created by vboxwrapper) // These are communicated via the app_status message channel char web_graphics_url[256]; + char remote_desktop_connection[256]; void set_task_state(int, const char*); inline int task_state() { diff --git a/client/app_control.cpp b/client/app_control.cpp index 3ba5efe90f..922523adbc 100644 --- a/client/app_control.cpp +++ b/client/app_control.cpp @@ -1206,6 +1206,7 @@ void ACTIVE_TASK::get_graphics_msg() { if (!app_client_shm.shm) return; if (app_client_shm.shm->graphics_reply.get_msg(msg_buf)) { parse_str(msg_buf, "", web_graphics_url, sizeof(web_graphics_url)); + parse_str(msg_buf, "", remote_desktop_connection, sizeof(remote_desktop_connection)); } } diff --git a/clientgui/Events.h b/clientgui/Events.h index 47a9997005..d40f455130 100644 --- a/clientgui/Events.h +++ b/clientgui/Events.h @@ -125,6 +125,7 @@ #define ID_TASK_WORK_SHOWGRAPHICS 9202 #define ID_TASK_WORK_ABORT 9203 #define ID_TASK_SHOW_PROPERTIES 9204 +#define ID_TASK_WORK_VMCONSOLE 9205 #define ID_TASK_TRANSFERS_RETRYNOW 9300 #define ID_TASK_TRANSFERS_ABORT 9301 #define ID_TASK_MESSAGES_COPYALL 9400 diff --git a/clientgui/MainDocument.cpp b/clientgui/MainDocument.cpp index c2d4fc1ec6..fac5470de9 100644 --- a/clientgui/MainDocument.cpp +++ b/clientgui/MainDocument.cpp @@ -1738,7 +1738,7 @@ int CMainDocument::WorkShowGraphics(RESULT* result) { // If graphics app is already running, don't launch a second instance // if (previous_gfx_app) return 0; - argv[0] =0; + argv[0] = 0; iRetVal = run_program( result->slot_path, @@ -1761,6 +1761,23 @@ int CMainDocument::WorkShowGraphics(RESULT* result) { } +int CMainDocument::WorkShowVMConsole(RESULT* result) { + int iRetVal = 0; + + if (strlen(result->remote_desktop_connection)) { + wxString strConnection(result->remote_desktop_connection, wxConvUTF8); + +#ifdef __WXMSW__ + wxString strCommand; + strCommand = wxT("mstsc.exe /v:") + strConnection + wxT(" /admin /w:640 /h:480"); + wxExecute(strCommand); +#endif + } + + return iRetVal; +} + + int CMainDocument::WorkAbort(char* url, char* name) { int iRetVal = 0; diff --git a/clientgui/MainDocument.h b/clientgui/MainDocument.h index 89c778f1ea..8ba380c276 100644 --- a/clientgui/MainDocument.h +++ b/clientgui/MainDocument.h @@ -270,6 +270,7 @@ public: int WorkSuspend(char* url, char* name); int WorkResume(char* url, char* name); int WorkShowGraphics(RESULT* result); + int WorkShowVMConsole(RESULT* result); int WorkAbort(char* url, char* name); CC_STATE* GetState() { return &state; }; diff --git a/clientgui/ViewWork.cpp b/clientgui/ViewWork.cpp index d050920e32..aa118f13ae 100644 --- a/clientgui/ViewWork.cpp +++ b/clientgui/ViewWork.cpp @@ -52,9 +52,10 @@ // buttons in the "tasks" area #define BTN_ACTIVE_ONLY 0 #define BTN_GRAPHICS 1 -#define BTN_SUSPEND 2 -#define BTN_ABORT 3 -#define BTN_PROPERTIES 4 +#define BTN_VMCONSOLE 2 +#define BTN_SUSPEND 3 +#define BTN_ABORT 4 +#define BTN_PROPERTIES 5 CWork::CWork() { @@ -83,6 +84,7 @@ IMPLEMENT_DYNAMIC_CLASS(CViewWork, CBOINCBaseView) BEGIN_EVENT_TABLE (CViewWork, CBOINCBaseView) EVT_BUTTON(ID_TASK_WORK_SUSPEND, CViewWork::OnWorkSuspend) EVT_BUTTON(ID_TASK_WORK_SHOWGRAPHICS, CViewWork::OnWorkShowGraphics) + EVT_BUTTON(ID_TASK_WORK_VMCONSOLE, CViewWork::OnWorkShowVMConsole) EVT_BUTTON(ID_TASK_WORK_ABORT, CViewWork::OnWorkAbort) EVT_BUTTON(ID_TASK_SHOW_PROPERTIES, CViewWork::OnShowItemProperties) EVT_BUTTON(ID_TASK_ACTIVE_ONLY, CViewWork::OnActiveTasksOnly) @@ -194,6 +196,13 @@ CViewWork::CViewWork(wxNotebook* pNotebook) : ); pGroup->m_Tasks.push_back( pItem ); + pItem = new CTaskItem( + _("Show VM Console"), + _("Show VM Console in a window."), + ID_TASK_WORK_VMCONSOLE + ); + pGroup->m_Tasks.push_back( pItem ); + pItem = new CTaskItem( _("Suspend"), _("Suspend work for this result."), @@ -361,6 +370,7 @@ void CViewWork::OnWorkSuspend( wxCommandEvent& WXUNUSED(event) ) { wxLogTrace(wxT("Function Start/End"), wxT("CViewWork::OnWorkSuspend - Function End")); } + void CViewWork::OnWorkShowGraphics( wxCommandEvent& WXUNUSED(event) ) { wxLogTrace(wxT("Function Start/End"), wxT("CViewWork::OnWorkShowGraphics - Function Begin")); @@ -398,6 +408,43 @@ void CViewWork::OnWorkShowGraphics( wxCommandEvent& WXUNUSED(event) ) { } +void CViewWork::OnWorkShowVMConsole( wxCommandEvent& WXUNUSED(event) ) { + wxLogTrace(wxT("Function Start/End"), wxT("CViewWork::OnWorkShowVMConsole - Function Begin")); + + CMainDocument* pDoc = wxGetApp().GetDocument(); + CAdvancedFrame* pFrame = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame); + RESULT* result; + int row; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + wxASSERT(pFrame); + wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame)); + wxASSERT(m_pListPane); + + pFrame->UpdateStatusText(_("Showing VM console for task...")); + + row = -1; + while (1) { + // Step through all selected items + row = m_pListPane->GetNextItem(row, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (row < 0) break; + + result = pDoc->result(m_iSortedIndexes[row]); + if (result) { + pDoc->WorkShowVMConsole(result); + } + } + + pFrame->UpdateStatusText(wxT("")); + + UpdateSelection(); + pFrame->FireRefreshView(); + + wxLogTrace(wxT("Function Start/End"), wxT("CViewWork::OnWorkShowVMConsole - Function End")); +} + + void CViewWork::OnWorkAbort( wxCommandEvent& WXUNUSED(event) ) { wxLogTrace(wxT("Function Start/End"), wxT("CViewWork::OnWorkAbort - Function Begin")); @@ -671,8 +718,10 @@ void CViewWork::UpdateSelection() { CMainDocument* pDoc = wxGetApp().GetDocument(); std::string first_project_url; wxString strMachineName; - bool wasSuspended=false, all_same_project=false; + bool wasSuspended=false; + bool all_same_project=false; bool enableShowGraphics = false; + bool enableShowVMConsole = false; bool enableSuspendResume = false; bool enableAbort = false; bool enableProperties = false; @@ -688,17 +737,20 @@ void CViewWork::UpdateSelection() { n = m_pListPane->GetSelectedItemCount(); if (n > 0) { enableShowGraphics = true; + enableShowVMConsole = true; enableSuspendResume = true; enableAbort = true; pDoc->GetCoreClientStatus(status); if (status.task_suspend_reason & ~(SUSPEND_REASON_CPU_THROTTLE)) { enableShowGraphics = false; + enableShowVMConsole = false; } pDoc->GetConnectedComputerName(strMachineName); if (!pDoc->IsComputerNameLocal(strMachineName)) { enableShowGraphics = false; + enableShowVMConsole = false; } } @@ -747,6 +799,13 @@ void CViewWork::UpdateSelection() { } } + // Disable Show VM console if the selected task hasn't registered a remote + // desktop connection + // + if (!strlen(result->remote_desktop_connection)) { + enableShowVMConsole = false; + } + // Disable Show Graphics button if the selected task can't display graphics // if (!strlen(result->web_graphics_url) && !strlen(result->graphics_exec_path)) { @@ -785,6 +844,13 @@ void CViewWork::UpdateSelection() { // To minimize flicker, set each button only once to the final desired state pGroup->m_Tasks[BTN_GRAPHICS]->m_pButton->Enable(enableShowGraphics); + if (enableShowVMConsole) { + pGroup->m_Tasks[BTN_VMCONSOLE]->m_pButton->Enable(); + pGroup->m_Tasks[BTN_VMCONSOLE]->m_pButton->Show(); + } else { + pGroup->m_Tasks[BTN_VMCONSOLE]->m_pButton->Disable(); + pGroup->m_Tasks[BTN_VMCONSOLE]->m_pButton->Hide(); + } pGroup->m_Tasks[BTN_SUSPEND]->m_pButton->Enable(enableSuspendResume); pGroup->m_Tasks[BTN_ABORT]->m_pButton->Enable(enableAbort); pGroup->m_Tasks[BTN_PROPERTIES]->m_pButton->Enable(enableProperties); diff --git a/clientgui/ViewWork.h b/clientgui/ViewWork.h index 289c867e8e..5c61a5fc52 100644 --- a/clientgui/ViewWork.h +++ b/clientgui/ViewWork.h @@ -69,6 +69,7 @@ public: void OnWorkSuspend( wxCommandEvent& event ); void OnWorkShowGraphics( wxCommandEvent& event ); + void OnWorkShowVMConsole( wxCommandEvent& event ); void OnWorkAbort( wxCommandEvent& event ); void OnShowItemProperties( wxCommandEvent& event ); void OnActiveTasksOnly( wxCommandEvent& event ); diff --git a/lib/gui_rpc_client.h b/lib/gui_rpc_client.h index 2e088538e1..b228b9e6f8 100644 --- a/lib/gui_rpc_client.h +++ b/lib/gui_rpc_client.h @@ -277,6 +277,7 @@ public: bool edf_scheduled; char graphics_exec_path[512]; char web_graphics_url[256]; + char remote_desktop_connection[256]; char slot_path[512]; // only present if graphics_exec_path is char resources[256]; diff --git a/lib/gui_rpc_client_ops.cpp b/lib/gui_rpc_client_ops.cpp index 7a2c22477c..54ed6d3981 100644 --- a/lib/gui_rpc_client_ops.cpp +++ b/lib/gui_rpc_client_ops.cpp @@ -535,6 +535,7 @@ int RESULT::parse(XML_PARSER& xp) { if (xp.parse_bool("edf_scheduled", edf_scheduled)) continue; if (xp.parse_str("graphics_exec_path", graphics_exec_path, sizeof(graphics_exec_path))) continue; if (xp.parse_str("web_graphics_url", web_graphics_url, sizeof(web_graphics_url))) continue; + if (xp.parse_str("remote_desktop_connection", remote_desktop_connection, sizeof(remote_desktop_connection))) continue; if (xp.parse_str("slot_path", slot_path, sizeof(slot_path))) continue; if (xp.parse_str("resources", resources, sizeof(resources))) continue; } @@ -549,6 +550,7 @@ void RESULT::clear() { strcpy(project_url, ""); strcpy(graphics_exec_path, ""); strcpy(web_graphics_url, ""); + strcpy(remote_desktop_connection, ""); strcpy(slot_path, ""); strcpy(resources, ""); report_deadline = 0;