source: trunk/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs @ 15583

Last change on this file since 15583 was 15583, checked in by swagner, 2 years ago

#2640: Updated year of copyrights in license headers

File size: 20.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.ServiceModel.Security;
27using System.Threading;
28using System.Threading.Tasks;
29using System.Windows.Forms;
30using HeuristicLab.Clients.Access;
31using HeuristicLab.Clients.Hive.Views;
32using HeuristicLab.Core;
33using HeuristicLab.Core.Views;
34using HeuristicLab.MainForm;
35using TS = System.Threading.Tasks;
36
37namespace HeuristicLab.Clients.Hive.Administrator.Views {
38  [View("Resources View")]
39  [Content(typeof(IItemList<Resource>), false)]
40  public partial class ResourcesView : ItemView, IDisposable {
41    public new IItemList<Resource> Content {
42      get { return (IItemList<Resource>)base.Content; }
43      set { base.Content = value; }
44    }
45
46    public const string UngroupedGroupName = "UNGROUPED";
47    private const int slaveImageIndex = 0;
48    private const int slaveGroupImageIndex = 1;
49    private readonly Color ownedResourceColor = Color.LightGreen;
50    private TS.Task progressTask;
51    private bool stopProgressTask;
52    private bool currentlyAuthorized;
53
54
55    public ResourcesView() {
56      InitializeComponent();
57      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
58      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
59
60      HiveAdminClient.Instance.Refreshing += new EventHandler(Instance_Refreshing);
61      HiveAdminClient.Instance.Refreshed += new EventHandler(Instance_Refreshed);
62
63      Access.AccessClient.Instance.Refreshing += new EventHandler(AccessClient_Refreshing);
64      Access.AccessClient.Instance.Refreshed += new EventHandler(AccessClient_Refreshed);
65    }
66
67    private void UpdateProgress() {
68      while (!stopProgressTask) {
69        int diff = (progressBar.Maximum - progressBar.Minimum) / 10;
70
71        if (progressBar.InvokeRequired) {
72          progressBar.Invoke(new Action(delegate() { progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum; }));
73        } else {
74          progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum;
75        }
76
77        //ok, this is not very clever...
78        Thread.Sleep(500);
79      }
80      if (progressBar.InvokeRequired) {
81        progressBar.Invoke(new Action(delegate() { progressBar.Value = progressBar.Minimum; }));
82      } else {
83        progressBar.Value = progressBar.Minimum;
84      }
85    }
86
87    void Instance_Refreshing(object sender, EventArgs e) {
88      stopProgressTask = false;
89      progressTask = new TS.Task(UpdateProgress);
90      progressTask.Start();
91      SetEnabledStateOfControls();
92    }
93
94    void Instance_Refreshed(object sender, EventArgs e) {
95      stopProgressTask = true;
96      SetEnabledStateOfControls();
97    }
98
99    void AccessClient_Refreshing(object sender, EventArgs e) {
100      stopProgressTask = false;
101      progressTask = new TS.Task(UpdateProgress);
102      progressTask.Start();
103      SetEnabledStateOfControls();
104      btnPermissionsSave.Enabled = false;
105    }
106
107    void AccessClient_Refreshed(object sender, EventArgs e) {
108      stopProgressTask = true;
109      SetEnabledStateOfControls();
110    }
111
112    #region Register Content Events
113    protected override void DeregisterContentEvents() {
114      Content.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
115      Content.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
116      base.DeregisterContentEvents();
117    }
118    protected override void RegisterContentEvents() {
119      base.RegisterContentEvents();
120      Content.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
121      Content.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
122    }
123    #endregion
124
125    protected override void OnContentChanged() {
126      base.OnContentChanged();
127      if (Content == null) {
128        slaveView.Content = null;
129        scheduleView.Content = null;
130        permissionView.Content = null;
131        permissionView.FetchSelectedUsers = null;
132        treeSlaveGroup.Nodes.Clear();
133      } else {
134        permissionView.Content = Access.AccessClient.Instance;
135        treeSlaveGroup.Nodes.Clear();
136
137        //rebuild
138        TreeNode ungrp = new TreeNode(UngroupedGroupName);
139        ungrp.ImageIndex = slaveGroupImageIndex;
140        ungrp.SelectedImageIndex = ungrp.ImageIndex;
141        var newGroup = new SlaveGroup();
142        newGroup.Name = UngroupedGroupName;
143        newGroup.Id = Guid.NewGuid();
144        newGroup.Description = "Contains slaves which are in no group";
145        ungrp.Tag = newGroup;
146
147        foreach (Resource g in Content) {
148          if (g.GetType() == typeof(SlaveGroup)) {
149            //root node
150            if (g.ParentResourceId == null) {
151              TreeNode tn = new TreeNode();
152              tn.ImageIndex = slaveGroupImageIndex;
153              tn.SelectedImageIndex = tn.ImageIndex;
154
155              tn.Tag = g;
156              tn.Text = g.Name;
157              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) tn.BackColor = ownedResourceColor;
158
159              BuildSlaveGroupTree(g, tn);
160              treeSlaveGroup.Nodes.Add(tn);
161            }
162          } else if (g.GetType() == typeof(Slave)) {
163            if (g.ParentResourceId == null) {
164              var stn = new TreeNode(g.Name);
165              stn.ImageIndex = slaveImageIndex;
166              stn.SelectedImageIndex = stn.ImageIndex;
167              stn.Tag = g;
168              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
169              ungrp.Nodes.Add(stn);
170            }
171          }
172        }
173        treeSlaveGroup.Nodes.Add(ungrp);
174      }
175    }
176
177    private void BuildSlaveGroupTree(Resource g, TreeNode tn) {
178      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == g.Id)) {
179        TreeNode stn = new TreeNode(r.Name);
180        if (r is Slave) {
181          stn.ImageIndex = slaveImageIndex;
182        } else if (r is SlaveGroup) {
183          stn.ImageIndex = slaveGroupImageIndex;
184        }
185        stn.SelectedImageIndex = stn.ImageIndex;
186        stn.Tag = r;
187        if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
188        tn.Nodes.Add(stn);
189
190        BuildSlaveGroupTree(r, stn);
191      }
192    }
193
194    protected override void SetEnabledStateOfControls() {
195      base.SetEnabledStateOfControls();
196      if (Content == null) {
197        btnAddGroup.Enabled = false;
198        btnRemoveGroup.Enabled = false;
199        btnSave.Enabled = false;
200        btnPermissionsSave.Enabled = false;
201        permissionView.Enabled = false;
202        scheduleView.SetEnabledStateOfSchedule(false);
203        btnPermissionsSave.Enabled = false;
204        permissionView.Enabled = false;
205      } else {
206        btnAddGroup.Enabled = true;
207        btnRemoveGroup.Enabled = true;
208        btnSave.Enabled = true;
209        scheduleView.SetEnabledStateOfSchedule(IsAuthorized(slaveView.Content));
210        btnPermissionsSave.Enabled = permissionView.FetchSelectedUsers != null;
211        permissionView.Enabled = permissionView.FetchSelectedUsers != null;
212      }
213    }
214
215    private bool IsAuthorized(Resource resource) {
216      return resource != null
217          && resource.Name != UngroupedGroupName
218          && resource.Id != Guid.Empty
219          && UserInformation.Instance.UserExists
220          && (resource.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
221    }
222
223    private void treeSlaveGroup_AfterSelect(object sender, TreeViewEventArgs e) {
224      if (e.Action != TreeViewAction.Unknown) {
225        Resource selectedResource = ((Resource)e.Node.Tag);
226        currentlyAuthorized = IsAuthorized(selectedResource);
227        if (currentlyAuthorized) {
228          permissionView.FetchSelectedUsers = new Func<List<Guid>>(() => {
229            return HiveServiceLocator.Instance.CallHiveService<List<ResourcePermission>>(service => {
230              return service.GetResourcePermissions(selectedResource.Id);
231            }).Select(x => x.GrantedUserId).ToList();
232          });
233          if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
234        } else {
235          permissionView.FetchSelectedUsers = null;
236          btnPermissionsSave.Enabled = false;
237          if (selectedResource.Id == Guid.Empty) {
238            if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
239          } else tabSlaveGroup.TabPages.Remove(tabPermissions);
240        }
241
242        if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
243          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
244        }
245
246        slaveView.Content = selectedResource;
247        HiveAdminClient.Instance.DowntimeForResourceId = selectedResource.Id;
248
249        if (selectedResource is SlaveGroup) {
250          slaveView.Content.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
251        }
252
253        if (tabSlaveGroup.SelectedIndex == 1) {
254          UpdateScheduleAsync();
255        } else if (tabSlaveGroup.SelectedIndex == 2) {
256          UpdatePermissionsAsync();
257        }
258      }
259    }
260
261    void SlaveViewContent_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
262      OnContentChanged();
263      if (e.PropertyName == "HbInterval") {
264        UpdateChildHbIntervall(slaveView.Content);
265      }
266    }
267
268    private void UpdateChildHbIntervall(Resource resource) {
269      foreach (Resource r in Content.Where(x => x.ParentResourceId == resource.Id)) {
270        r.HbInterval = resource.HbInterval;
271        if (r is SlaveGroup) {
272          UpdateChildHbIntervall(r);
273        }
274      }
275    }
276
277    private void btnAddGroup_Click(object sender, EventArgs e) {
278      SlaveGroup newGroup = new SlaveGroup();
279      newGroup.Name = "New Group";
280      newGroup.OwnerUserId = UserInformation.Instance.User.Id;
281      Content.Add(newGroup);
282    }
283
284    void Content_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
285      OnContentChanged();
286    }
287
288    void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
289      OnContentChanged();
290    }
291
292    private void btnRemoveGroup_Click(object sender, EventArgs e) {
293      if (treeSlaveGroup.SelectedNode != null && treeSlaveGroup.SelectedNode.Tag != null) {
294        Resource res = (Resource)treeSlaveGroup.SelectedNode.Tag;
295
296        DialogResult diagRes = MessageBox.Show("Do you really want to delete " + res.Name + "?", "HeuristicLab Hive Administrator", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
297        if (diagRes == DialogResult.Yes) {
298          if (res is Slave) {
299            Content.Remove(res);
300            HiveAdminClient.Delete(res);
301          } else if (res is SlaveGroup) {
302            //only delete empty groups
303            if (Content.Where(s => s.ParentResourceId == res.Id).Count() < 1) {
304              Content.Remove(res);
305              HiveAdminClient.Delete(res);
306            } else {
307              MessageBox.Show("Only empty groups can be deleted.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
308            }
309          }
310        }
311      }
312    }
313
314    private void btnSave_Click(object sender, EventArgs e) {
315      foreach (Resource res in Content) {
316        if (res is SlaveGroup && res.Id == Guid.Empty) {
317          SlaveGroup slaveGroup = (SlaveGroup)res;
318          slaveGroup.Store();
319        } else if (res.Id != Guid.Empty && res.Modified) {
320          res.Store();
321        }
322      }
323    }
324
325    private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
326      if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false)) {
327        Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
328        TreeNode destNode = ((TreeView)sender).GetNodeAt(pt);
329        TreeNode newNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
330
331        if (destNode.TreeView == newNode.TreeView) {
332          if (destNode.Text == UngroupedGroupName || (destNode.Parent != null && destNode.Parent.Text == UngroupedGroupName)) {
333            MessageBox.Show(string.Format("You can't drag items to the group \"{0}\".{1}This group only contains slaves which haven't yet been assigned to a real group.",
334              UngroupedGroupName, Environment.NewLine), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Information);
335            return;
336          }
337
338          SlaveGroup sgrp = null;
339          TreeNode parentNode = null;
340          if (destNode.Tag != null && destNode.Tag is SlaveGroup) {
341            sgrp = (SlaveGroup)destNode.Tag;
342            parentNode = destNode;
343          } else if (destNode.Parent != null && destNode.Parent.Tag is SlaveGroup) {
344            sgrp = (SlaveGroup)destNode.Parent.Tag;
345            parentNode = destNode.Parent;
346          }
347
348          if (newNode.Tag is SlaveGroup && CheckParentsEqualsMovedNode(parentNode, newNode)) {
349            return;
350          }
351
352          SlaveGroup parent = (SlaveGroup)parentNode.Tag;
353
354          if (parent.OwnerUserId != null && !IsAuthorized(parent)) {
355            MessageBox.Show(string.Format("You don't have the permissions to drag items to the group \"{0}\".", ((Resource)parentNode.Tag).Name),
356              "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
357            return;
358          }
359
360          if (sgrp != null && newNode.Tag != null) {
361            //save parent group to get an id
362            if (sgrp.Id == Guid.Empty) {
363              sgrp.Store();
364            }
365
366            if (newNode.Tag is Slave) {
367              Slave slave = (Slave)newNode.Tag;
368              if (slave.ParentResourceId == null || (slave.ParentResourceId != null && slave.ParentResourceId != sgrp.Id)) {
369                slave.ParentResourceId = sgrp.Id;
370                newNode.Remove();
371                parentNode.Nodes.Clear();
372                BuildSlaveGroupTree(sgrp, parentNode);
373              }
374            } else if (newNode.Tag is SlaveGroup) {
375              SlaveGroup slaveGroup = (SlaveGroup)newNode.Tag;
376              if (slaveGroup.ParentResourceId == null || (slaveGroup.ParentResourceId != null && slaveGroup.ParentResourceId != sgrp.Id)) {
377                slaveGroup.ParentResourceId = sgrp.Id;
378                newNode.Remove();
379                parentNode.Nodes.Clear();
380                BuildSlaveGroupTree(sgrp, parentNode);
381              }
382            }
383          }
384        }
385      }
386    }
387
388    private bool CheckParentsEqualsMovedNode(TreeNode dest, TreeNode movedNode) {
389      TreeNode tmp = dest;
390
391      while (tmp != null) {
392        if (tmp == movedNode) {
393          return true;
394        }
395        tmp = tmp.Parent;
396      }
397      return false;
398    }
399
400    private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
401      TreeNode sourceNode = (TreeNode)e.Item;
402      if (IsAuthorized((Resource)sourceNode.Tag))
403        DoDragDrop(sourceNode, DragDropEffects.All);
404    }
405
406    private void treeSlaveGroup_DragEnter(object sender, DragEventArgs e) {
407      e.Effect = DragDropEffects.Move;
408    }
409
410    private void treeSlaveGroup_DragOver(object sender, DragEventArgs e) {
411      e.Effect = DragDropEffects.Move;
412    }
413
414    private void treeSlaveGroup_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
415      e.Action = DragAction.Continue;
416    }
417
418    void ResetView() {
419      if (this.InvokeRequired) {
420        Invoke(new Action(ResetView));
421      } else {
422        treeSlaveGroup.Nodes.Clear();
423
424        if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
425          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
426        }
427        slaveView.Content = null;
428        if (scheduleView.Content != null) {
429          scheduleView.Content.Clear();
430        }
431        HiveAdminClient.Instance.ResetDowntime();
432      }
433    }
434
435    private void UpdateResources() {
436      ResetView();
437
438      try {
439        if (!Access.UserInformation.Instance.UserExists) {
440          //do a refresh just in case that the user has changed his usr and pwd in between
441          Access.UserInformation.Instance.Refresh();
442        }
443        HiveAdminClient.Instance.Refresh();
444        Content = HiveAdminClient.Instance.Resources;
445      }
446      catch (MessageSecurityException) {
447        ShowMessageSecurityException();
448      }
449      catch (AnonymousUserException) {
450        ShowHiveInformationDialog();
451      }
452    }
453
454    private void ShowMessageSecurityException() {
455      if (this.InvokeRequired) {
456        Invoke(new Action(ShowMessageSecurityException));
457      } else {
458        MessageBox.Show("A Message Security error has occured. This normally means that your user name or password is wrong.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
459      }
460    }
461
462    private void ShowHiveInformationDialog() {
463      if (this.InvokeRequired) {
464        Invoke(new Action(ShowHiveInformationDialog));
465      } else {
466        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
467          dialog.ShowDialog(this);
468        }
469      }
470    }
471
472    private void UpdateResourcesAsync() {
473      TS.Task.Factory.StartNew(UpdateResources).ContinueWith((t) => {
474        DisplayError(t.Exception);
475      }, TaskContinuationOptions.OnlyOnFaulted);
476    }
477
478    private void UpdateSchedule() {
479      HiveAdminClient.Instance.RefreshCalendar();
480      scheduleView.Invoke(new Action(() => {
481        scheduleView.Content = HiveAdminClient.Instance.Downtimes;
482        SetEnabledStateOfControls();
483      }));
484    }
485
486    private void UpdateScheduleAsync() {
487      TS.Task.Factory.StartNew(UpdateSchedule).ContinueWith((t) => {
488        DisplayError(t.Exception);
489      }, TaskContinuationOptions.OnlyOnFaulted);
490    }
491
492    private void UpdatePermissions() {
493      if (permissionView.Content != null && permissionView.FetchSelectedUsers != null)
494        permissionView.Invoke(new Action(() => permissionView.ManualRefresh()));
495    }
496
497    private void UpdatePermissionsAsync() {
498      TS.Task.Factory.StartNew(UpdatePermissions).ContinueWith((t) => {
499        DisplayError(t.Exception);
500      }, TaskContinuationOptions.OnlyOnFaulted);
501    }
502
503
504    private void DisplayError(Exception ex) {
505      MessageBox.Show(string.Format("An error occured while updating: {0} {1}", Environment.NewLine, ex.Message), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
506    }
507
508    private void tabSlaveGroup_SelectedIndexChanged(object sender, EventArgs e) {
509      if (tabSlaveGroup.SelectedIndex == 1) {
510        UpdateScheduleAsync();
511      } else if (tabSlaveGroup.SelectedIndex == 2) {
512        UpdatePermissionsAsync();
513      }
514    }
515
516    private void btnRefresh_Click(object sender, EventArgs e) {
517      UpdateResourcesAsync();
518    }
519
520    private void ResourcesView_Load(object sender, EventArgs e) {
521      UpdateResourcesAsync();
522    }
523
524    private void btnPermissionsSave_Click(object sender, EventArgs e) {
525      SetEnabledStateOfControls();
526      HiveServiceLocator.Instance.CallHiveService(service => {
527        service.GrantResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetAddedUsers().Select(x => x.Id).ToList());
528        service.RevokeResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetDeletedUsers().Select(x => x.Id).ToList());
529      });
530      SetEnabledStateOfControls();
531    }
532  }
533}
Note: See TracBrowser for help on using the repository browser.