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;