Salome HOME
Explicitly indicate batch managers with limited support
[modules/jobmanager.git] / src / genericgui / JM_EditSalomeResource.cxx
1 // Copyright (C) 2009-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "JM_EditSalomeResource.hxx"
21 #include "BL_Traces.hxx"
22
23 using namespace std;
24
25 JM::EditSalomeResource::EditSalomeResource(QWidget *parent, BL::SALOMEServices * salome_services,
26                                            const std::string & resource_name) : QDialog(parent)
27 {
28   DEBTRACE("Creating JM::EditSalomeResource");
29   BL_ASSERT(parent);
30   BL_ASSERT(salome_services);
31   _parent = parent;
32   _salome_services = salome_services;
33   _resource_name = resource_name;
34
35   //setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
36
37   // Widget code
38
39   // Part 1
40   QGroupBox * main_groupBox = new QGroupBox("Main values");
41   QLabel * name_label = new QLabel("Name:");
42   _name_line = new QLineEdit(this);
43   QLabel * hostname_label = new QLabel("Hostname:");
44   _hostname_line = new QLineEdit(this);
45   QLabel * username_label = new QLabel("Username:");
46   _username_line = new QLineEdit(this);
47   QLabel * applipath_label = new QLabel("Applipath:");
48   _applipath_line = new QLineEdit(this);
49
50   QLabel * protocol_label = new QLabel("Protocol:");
51   _protocol_line = new QComboBox(this);
52   _protocol_line->addItem("ssh");
53   _protocol_line->addItem("rsh");
54   _protocol_line->addItem("sh");
55   _protocol_line->setCurrentIndex(0);
56
57   QLabel * componentList_label = new QLabel("Component List:");
58   _add_button = new QPushButton("Add");
59   _remove_button = new QPushButton("Remove");
60   _remove_button->setEnabled(false);
61   QWidget * component_widget = new QWidget(this);
62   _componentList = new QListWidget(this);
63   _componentList->setSelectionMode(QAbstractItemView::MultiSelection);
64   QGridLayout * input_box = new QGridLayout(this);
65   input_box->addWidget(_add_button, 0, 0);
66   input_box->addWidget(_remove_button, 0, 1);
67   input_box->addWidget(_componentList, 1, 0, 1, -1);
68   component_widget->setLayout(input_box);
69   connect(_add_button, SIGNAL(clicked()), this, SLOT(add_component()));
70   connect(_remove_button, SIGNAL(clicked()), this, SLOT(remove_components()));
71   connect(_componentList, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
72
73   QLabel * working_directory_label = new QLabel("Working Directory:");
74   _working_directory = new QLineEdit(this);
75   _can_launch_batch_jobs = new QCheckBox("This resource can be used to launch batch jobs", this);
76   _can_run_containers = new QCheckBox("This resource can be used to run interactive containers", this);
77
78   QGridLayout * m_layout = new QGridLayout;
79   m_layout->addWidget(name_label, 0, 0);
80   m_layout->addWidget(_name_line, 0, 1);
81   m_layout->addWidget(hostname_label, 1, 0);
82   m_layout->addWidget(_hostname_line, 1, 1);
83   m_layout->addWidget(protocol_label, 2, 0);
84   m_layout->addWidget(_protocol_line, 2, 1);
85   m_layout->addWidget(username_label, 3, 0);
86   m_layout->addWidget(_username_line, 3, 1);
87   m_layout->addWidget(applipath_label, 4, 0);
88   m_layout->addWidget(_applipath_line, 4, 1);
89   m_layout->addWidget(componentList_label, 5, 0);
90   m_layout->addWidget(component_widget, 5, 1);
91   m_layout->addWidget(working_directory_label, 6, 0);
92   m_layout->addWidget(_working_directory, 6, 1);
93   m_layout->addWidget(_can_launch_batch_jobs, 7, 1);
94   m_layout->addWidget(_can_run_containers, 8, 1);
95   main_groupBox->setLayout(m_layout);
96
97   // Part 2
98   QGroupBox * config_groupBox = new QGroupBox("Configuration values");
99   QLabel * os_label = new QLabel("OS:");
100   _os_line = new QLineEdit(this);
101
102   QLabel * mem_mb_label = new QLabel("Memory (mb):");
103   _mem_mb_line = new QSpinBox(this);
104   _mem_mb_line->setMinimum(0);
105   _mem_mb_line->setMaximum(1000000);
106   _mem_mb_line->setValue(0);
107   QLabel * cpu_clock_label = new QLabel("CPU Clock:");
108   _cpu_clock_line = new QSpinBox(this);
109   _cpu_clock_line->setMinimum(0);
110   _cpu_clock_line->setMaximum(1000000);
111   _cpu_clock_line->setValue(0);
112   QLabel * nb_node_label = new QLabel("Nb node:");
113   _nb_node_line = new QSpinBox(this);
114   _nb_node_line->setMinimum(1);
115   _nb_node_line->setMaximum(1000000);
116   _nb_node_line->setValue(1);
117   QLabel * nb_proc_per_node_label = new QLabel("Nb proc/node:");
118   _nb_proc_per_node_line = new QSpinBox(this);
119   _nb_proc_per_node_line->setMinimum(1);
120   _nb_proc_per_node_line->setMaximum(1000000);
121   _nb_proc_per_node_line->setValue(1);
122
123   QLabel * iprotocol_label = new QLabel("Internal protocol:");
124   _iprotocol_line = new QComboBox(this);
125   _iprotocol_line->addItem("ssh");
126   _iprotocol_line->addItem("rsh");
127   _iprotocol_line->addItem("srun");
128   _iprotocol_line->addItem("pbsdsh");
129   _iprotocol_line->addItem("blaunch");
130   _iprotocol_line->setCurrentIndex(0);
131
132   QLabel * batch_label = new QLabel("Batch Manager:");
133   _batch_line = new QComboBox(this);
134   _batch_line->addItem("None", "ssh_batch");
135   _batch_line->addItem("CCC", "ccc");
136   _batch_line->addItem("LSF", "lsf");
137   _batch_line->addItem("SGE", "sge");
138   _batch_line->addItem("SLURM", "slurm");
139   _batch_line->addItem("VISHNU", "vishnu");
140   _batch_line->addItem("CooRM (limited support)", "coorm");
141   _batch_line->addItem("LoadLeveler (limited support)", "ll");
142   _batch_line->addItem("OAR (limited support)", "oar");
143   _batch_line->addItem("PBS (limited support)", "pbs");
144   _batch_line->setCurrentIndex(0);
145
146   QLabel * mpiImpl_label = new QLabel("MPI impl:");
147   _mpiImpl_line = new QComboBox(this);
148   _mpiImpl_line->addItem("lam");
149   _mpiImpl_line->addItem("mpich1");
150   _mpiImpl_line->addItem("mpich2");
151   _mpiImpl_line->addItem("openmpi");
152   _mpiImpl_line->addItem("slurmmpi");
153   _mpiImpl_line->addItem("prun");
154   _mpiImpl_line->setCurrentIndex(-1);
155
156   QGridLayout * c_layout = new QGridLayout;
157   c_layout->addWidget(os_label, 0, 0);
158   c_layout->addWidget(_os_line, 0, 1);
159   c_layout->addWidget(mem_mb_label, 1, 0);
160   c_layout->addWidget(_mem_mb_line, 1, 1);
161   c_layout->addWidget(cpu_clock_label, 2, 0);
162   c_layout->addWidget(_cpu_clock_line, 2, 1);
163   c_layout->addWidget(nb_node_label, 3, 0);
164   c_layout->addWidget(_nb_node_line, 3, 1);
165   c_layout->addWidget(nb_proc_per_node_label, 4, 0);
166   c_layout->addWidget(_nb_proc_per_node_line, 4, 1);
167   c_layout->addWidget(batch_label, 5, 0);
168   c_layout->addWidget(_batch_line, 5, 1);
169   c_layout->addWidget(mpiImpl_label, 6, 0);
170   c_layout->addWidget(_mpiImpl_line, 6, 1);
171   c_layout->addWidget(iprotocol_label, 7, 0);
172   c_layout->addWidget(_iprotocol_line, 7, 1);
173   config_groupBox->setLayout(c_layout);
174
175   // Part 3
176   QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
177                                                       | QDialogButtonBox::Cancel);
178
179   connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
180   connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
181
182   // Main Layout
183   QVBoxLayout * mainLayout = new QVBoxLayout(this);
184   mainLayout->addWidget(main_groupBox);
185   mainLayout->addWidget(config_groupBox);
186   mainLayout->addWidget(buttonBox);
187   setLayout(mainLayout);
188
189   setWindowTitle("Edit/Add a resource");
190   if (_resource_name != "")
191     get_infos();
192 }
193
194 JM::EditSalomeResource::~EditSalomeResource()
195 {
196   DEBTRACE("Destroying JM::EditSalomeResource");
197 }
198
199 void
200 JM::EditSalomeResource::get_infos()
201 {
202   BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(_resource_name);
203
204   _name_line->setText(QString(resource_descr.name.c_str()));
205   _hostname_line->setText(QString(resource_descr.hostname.c_str()));
206   _username_line->setText(QString(resource_descr.username.c_str()));
207   _applipath_line->setText(QString(resource_descr.applipath.c_str()));
208   _os_line->setText(QString(resource_descr.OS.c_str()));
209   _working_directory->setText(QString(resource_descr.working_directory.c_str()));
210
211   if (resource_descr.can_launch_batch_jobs)
212     _can_launch_batch_jobs->setCheckState(Qt::Checked);
213   else
214     _can_launch_batch_jobs->setCheckState(Qt::Unchecked);
215
216   if (resource_descr.can_run_containers)
217     _can_run_containers->setCheckState(Qt::Checked);
218   else
219     _can_run_containers->setCheckState(Qt::Unchecked);
220
221   std::string protocol = resource_descr.protocol.c_str();
222   if (protocol == "ssh")
223     _protocol_line->setCurrentIndex(0);
224   else if(protocol == "rsh")
225     _protocol_line->setCurrentIndex(1);
226   else if(protocol == "sh")
227     _protocol_line->setCurrentIndex(2);
228   else
229     _protocol_line->setCurrentIndex(-1);
230
231   std::string iprotocol = resource_descr.iprotocol.c_str();
232   if (iprotocol == "ssh")
233     _iprotocol_line->setCurrentIndex(0);
234   else if (iprotocol == "rsh")
235     _iprotocol_line->setCurrentIndex(1);
236   else if (iprotocol == "srun")
237     _iprotocol_line->setCurrentIndex(2);
238   else if (iprotocol == "pbsdsh")
239     _iprotocol_line->setCurrentIndex(3);
240   else if (iprotocol == "blaunch")
241     _iprotocol_line->setCurrentIndex(4);
242   else
243     _iprotocol_line->setCurrentIndex(-1);
244
245   for (int i=0 ; i<_batch_line->count() ; i++)
246   {
247     if (_batch_line->itemData(i).toString().toStdString() == resource_descr.batch)
248     {
249       _batch_line->setCurrentIndex(i);
250     }
251   }
252
253   std::string mpiImpl = resource_descr.mpiImpl.c_str();
254   if (mpiImpl == "lam")
255     _mpiImpl_line->setCurrentIndex(0);
256   else if (mpiImpl == "mpich1")  
257     _mpiImpl_line->setCurrentIndex(1);
258   else if (mpiImpl == "mpich2")  
259     _mpiImpl_line->setCurrentIndex(2);
260   else if (mpiImpl == "openmpi")
261     _mpiImpl_line->setCurrentIndex(3);
262   else if (mpiImpl == "slurmmpi")
263     _mpiImpl_line->setCurrentIndex(4);
264   else if (mpiImpl == "prun")
265     _mpiImpl_line->setCurrentIndex(5);
266   else  
267     _mpiImpl_line->setCurrentIndex(-1);
268
269   int value = resource_descr.mem_mb;
270   if (value > 0)
271     _mem_mb_line->setValue(value);
272   value = resource_descr.cpu_clock;
273   if (value > 0)
274     _cpu_clock_line->setValue(value);
275   value = resource_descr.nb_node;
276   if (value > 1)
277     _nb_node_line->setValue(value);
278   value = resource_descr.nb_proc_per_node;
279   if (value > 1)
280     _nb_proc_per_node_line->setValue(value);
281
282    std::list<std::string>::iterator it = resource_descr.componentList.begin();
283    for(; it != resource_descr.componentList.end(); it++)
284      _componentList->addItem(QString((*it).c_str()));
285    
286   // Better if string's length is bigger than the widget
287   _name_line->setCursorPosition(0);
288   _hostname_line->setCursorPosition(0);
289   _username_line->setCursorPosition(0);
290   _applipath_line->setCursorPosition(0);
291   _os_line->setCursorPosition(0);
292   _working_directory->setCursorPosition(0);
293 }
294
295
296 void 
297 JM::EditSalomeResource::itemSelectionChanged()
298 {
299   if (_componentList->selectedItems().size() > 0)
300     _remove_button->setEnabled(true);
301   else
302     _remove_button->setEnabled(false);
303 }
304
305 void 
306 JM::EditSalomeResource::add_component()
307 {
308   bool ok;
309   QString text = QInputDialog::getText(this, "Add a component",
310                                        "Component name:", QLineEdit::Normal,
311                                        "", &ok);
312   if (ok && !text.isEmpty())
313     _componentList->addItem(text);
314 }
315
316 void 
317 JM::EditSalomeResource::remove_components()
318 {
319   QList<QListWidgetItem *> list = _componentList->selectedItems();
320   for (int i = 0; i < list.size(); ++i)
321   {
322     int row = _componentList->row( list.at(i) );
323     delete _componentList->takeItem(row);
324   }
325 }
326
327 void
328 JM::EditSalomeResource::accept()
329 {
330   BL::ResourceDescr resource;
331
332   // Text
333   resource.name = _name_line->text().toStdString();
334   resource.hostname = _hostname_line->text().toStdString();
335   resource.username = _username_line->text().toStdString();
336   resource.applipath = _applipath_line->text().toStdString();
337   resource.OS = _os_line->text().toStdString();
338   resource.working_directory = _working_directory->text().toStdString();
339   resource.can_launch_batch_jobs = (_can_launch_batch_jobs->checkState() == Qt::Checked);
340   resource.can_run_containers = (_can_run_containers->checkState() == Qt::Checked);
341
342   // Components
343   int count = _componentList->count();
344   for (int i = 0; i < count; i++)
345     resource.componentList.push_back(_componentList->item(i)->text().toStdString());
346
347   // ComboBox
348   resource.protocol = _protocol_line->currentText().toStdString();
349   resource.iprotocol = _iprotocol_line->currentText().toStdString();
350   resource.batch = _batch_line->itemData(_batch_line->currentIndex()).toString().toStdString();
351   resource.mpiImpl = _mpiImpl_line->currentText().toStdString();
352
353   // QSpinBox
354   resource.mem_mb = _mem_mb_line->value();
355   resource.cpu_clock = _cpu_clock_line->value();
356   resource.nb_node = _nb_node_line->value();
357   resource.nb_proc_per_node = _nb_proc_per_node_line->value();
358
359   if (resource.name != "" &&
360       resource.hostname != "" &&
361       resource.protocol != "")
362   {
363     try
364     {
365       _salome_services->addResource(resource);
366       QDialog::accept();
367     }
368     catch (const BL::Exception & ex)
369     {
370       QMessageBox::critical(this, "Error", QString("Cannot add resource: ") + ex.what());
371     }
372   }
373   else
374   {
375     QMessageBox::warning(NULL, "Values missing", "name, hostname and protocol are mandatory! Cancel or add values!");
376   }
377 }