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