Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2877_HiveImprovements/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 15870

Last change on this file since 15870 was 15636, checked in by jkarder, 7 years ago

#2877: fixed overwriting of IsDisposable for known slaves

File size: 39.5 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.Linq;
25using System.Security;
26using System.ServiceModel;
27using HeuristicLab.Services.Access;
28using HeuristicLab.Services.Hive.DataAccess.Interfaces;
29using HeuristicLab.Services.Hive.DataTransfer;
30using HeuristicLab.Services.Hive.Manager;
31using HeuristicLab.Services.Hive.ServiceContracts;
32using DA = HeuristicLab.Services.Hive.DataAccess;
33using DT = HeuristicLab.Services.Hive.DataTransfer;
34
35namespace HeuristicLab.Services.Hive {
36  /// <summary>
37  /// Implementation of the Hive service (interface <see cref="IHiveService"/>).
38  /// We need 'IgnoreExtensionDataObject' Attribute for the slave to work.
39  /// </summary>
40  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IgnoreExtensionDataObject = true)]
41  [HiveOperationContextBehavior]
42  public class HiveService : IHiveService {
43    private static readonly DA.TaskState[] CompletedStates = { DA.TaskState.Finished, DA.TaskState.Aborted, DA.TaskState.Failed };
44
45    private IPersistenceManager PersistenceManager {
46      get { return ServiceLocator.Instance.PersistenceManager; }
47    }
48
49    private IUserManager UserManager {
50      get { return ServiceLocator.Instance.UserManager; }
51    }
52
53    private IRoleVerifier RoleVerifier {
54      get { return ServiceLocator.Instance.RoleVerifier; }
55    }
56
57    private IAuthorizationManager AuthorizationManager {
58      get { return ServiceLocator.Instance.AuthorizationManager; }
59    }
60    private IEventManager EventManager {
61      get { return ServiceLocator.Instance.EventManager; }
62    }
63    private HeartbeatManager HeartbeatManager {
64      get { return ServiceLocator.Instance.HeartbeatManager; }
65    }
66
67    #region Task Methods
68    public Guid AddTask(DT.Task task, DT.TaskData taskData, IEnumerable<Guid> resourceIds) {
69      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
70      var pm = PersistenceManager;
71      using (new PerformanceLogger("AddTask")) {
72        var taskDao = pm.TaskDao;
73        var stateLogDao = pm.StateLogDao;
74        var newTask = task.ToEntity();
75        newTask.JobData = taskData.ToEntity();
76        newTask.JobData.LastUpdate = DateTime.Now;
77        newTask.AssignedResources.AddRange(resourceIds.Select(
78          x => new DA.AssignedResource {
79            ResourceId = x
80          }));
81        newTask.State = DA.TaskState.Waiting;
82        return pm.UseTransaction(() => {
83          taskDao.Save(newTask);
84          pm.SubmitChanges();
85          stateLogDao.Save(new DA.StateLog {
86            State = DA.TaskState.Waiting,
87            DateTime = DateTime.Now,
88            TaskId = newTask.TaskId,
89            UserId = UserManager.CurrentUserId,
90            SlaveId = null,
91            Exception = null
92          });
93          pm.SubmitChanges();
94          return newTask.TaskId;
95        }, false, true);
96      }
97    }
98
99    public Guid AddChildTask(Guid parentTaskId, DT.Task task, DT.TaskData taskData) {
100      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
101      IEnumerable<Guid> resourceIds;
102      var pm = PersistenceManager;
103      using (new PerformanceLogger("AddChildTask")) {
104        var assignedResourceDao = pm.AssignedResourceDao;
105        resourceIds = pm.UseTransaction(() => {
106          return assignedResourceDao.GetByTaskId(parentTaskId)
107            .Select(x => x.ResourceId)
108            .ToList();
109        });
110      }
111      task.ParentTaskId = parentTaskId;
112      return AddTask(task, taskData, resourceIds);
113    }
114
115    public DT.Task GetTask(Guid taskId) {
116      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
117      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
118      var pm = PersistenceManager;
119      using (new PerformanceLogger("GetTask")) {
120        var taskDao = pm.TaskDao;
121        return pm.UseTransaction(() => {
122          var task = taskDao.GetById(taskId);
123          return task.ToDto();
124        });
125      }
126    }
127
128    public IEnumerable<DT.LightweightTask> GetLightweightJobTasks(Guid jobId) {
129      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
130      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
131      var pm = PersistenceManager;
132      using (new PerformanceLogger("GetLightweightJobTasks")) {
133        var taskDao = pm.TaskDao;
134        return pm.UseTransaction(() => {
135          return taskDao.GetByJobId(jobId)
136            .ToList()
137            .Select(x => new DT.LightweightTask {
138              Id = x.TaskId,
139              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
140              ParentTaskId = x.ParentTaskId,
141              StateLog = x.StateLogs.OrderBy(y => y.DateTime)
142                                    .Select(z => z.ToDto())
143                                    .ToList(),
144              State = x.State.ToDto(),
145              Command = x.Command.ToDto(),
146              LastTaskDataUpdate = x.JobData.LastUpdate
147            })
148            .ToList();
149        }, false, true);
150      }
151    }
152
153    public IEnumerable<DT.LightweightTask> GetLightweightJobTasksWithoutStateLog(Guid jobId) {
154      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
155      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
156      var pm = PersistenceManager;
157      using (new PerformanceLogger("GetLightweightJobTasksWithoutStateLog")) {
158        var taskDao = pm.TaskDao;
159        return pm.UseTransaction(() => {
160          return taskDao.GetByJobId(jobId)
161            .ToList()
162            .Select(x => new DT.LightweightTask {
163              Id = x.TaskId,
164              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
165              ParentTaskId = x.ParentTaskId,
166              StateLog = new List<DT.StateLog>(),
167              State = x.State.ToDto(),
168              Command = x.Command.ToDto(),
169              LastTaskDataUpdate = x.JobData.LastUpdate
170            })
171            .ToList();
172        }, false, true);
173      }
174    }
175
176    public DT.TaskData GetTaskData(Guid taskId) {
177      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
178      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
179      var pm = PersistenceManager;
180      using (new PerformanceLogger("GetTaskData")) {
181        var taskDataDao = pm.TaskDataDao;
182        return pm.UseTransaction(() => taskDataDao.GetById(taskId).ToDto());
183      }
184    }
185
186    public void UpdateTask(DT.Task taskDto) {
187      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
188      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
189      var pm = PersistenceManager;
190      using (new PerformanceLogger("UpdateTask")) {
191        var taskDao = pm.TaskDao;
192        pm.UseTransaction(() => {
193          var task = taskDao.GetById(taskDto.Id);
194          taskDto.CopyToEntity(task);
195          pm.SubmitChanges();
196        });
197      }
198    }
199
200    public void UpdateTaskData(DT.Task taskDto, DT.TaskData taskDataDto) {
201      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
202      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
203      var pm = PersistenceManager;
204      using (new PerformanceLogger("UpdateTaskData")) {
205        var taskDao = pm.TaskDao;
206        var taskDataDao = pm.TaskDataDao;
207        pm.UseTransaction(() => {
208          var task = taskDao.GetById(taskDto.Id);
209          var taskData = taskDataDao.GetById(taskDataDto.TaskId);
210          taskDto.CopyToEntity(task);
211          taskDataDto.CopyToEntity(taskData);
212          taskData.LastUpdate = DateTime.Now;
213          pm.SubmitChanges();
214        });
215      }
216    }
217
218    public DT.Task UpdateTaskState(Guid taskId, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
219      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
220      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
221      var pm = PersistenceManager;
222      using (new PerformanceLogger("UpdateTaskState")) {
223        var taskDao = pm.TaskDao;
224        return pm.UseTransaction(() => {
225          var task = taskDao.GetById(taskId);
226          UpdateTaskState(pm, task, taskState, slaveId, userId, exception);
227          pm.SubmitChanges();
228          return task.ToDto();
229        });
230      }
231    }
232    #endregion
233
234    #region Task Control Methods
235    public void StopTask(Guid taskId) {
236      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
237      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
238      var pm = PersistenceManager;
239      using (new PerformanceLogger("StopTask")) {
240        var taskDao = pm.TaskDao;
241        pm.UseTransaction(() => {
242          var task = taskDao.GetById(taskId);
243          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
244            task.Command = DA.Command.Stop;
245          } else if (task.State != DA.TaskState.Aborted
246                     && task.State != DA.TaskState.Finished
247                     && task.State != DA.TaskState.Failed) {
248            UpdateTaskState(pm, task, DT.TaskState.Aborted, null, null, string.Empty);
249          }
250          pm.SubmitChanges();
251        });
252      }
253    }
254
255    public void PauseTask(Guid taskId) {
256      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
257      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
258      var pm = PersistenceManager;
259      using (new PerformanceLogger("PauseTask")) {
260        var taskDao = pm.TaskDao;
261        pm.UseTransaction(() => {
262          var task = taskDao.GetById(taskId);
263          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
264            task.Command = DA.Command.Pause;
265          } else if (task.State != DA.TaskState.Paused
266                     && task.State != DA.TaskState.Aborted
267                     && task.State != DA.TaskState.Finished
268                     && task.State != DA.TaskState.Failed) {
269            UpdateTaskState(pm, task, DT.TaskState.Paused, null, null, string.Empty);
270          }
271          pm.SubmitChanges();
272        });
273      }
274    }
275
276    public void RestartTask(Guid taskId) {
277      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
278      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
279      var pm = PersistenceManager;
280      using (new PerformanceLogger("RestartTask")) {
281        var taskDao = pm.TaskDao;
282        pm.UseTransaction(() => {
283          var task = taskDao.GetById(taskId);
284          task.Command = null;
285          UpdateTaskState(pm, task, DT.TaskState.Waiting, null, UserManager.CurrentUserId, string.Empty);
286          pm.SubmitChanges();
287        });
288      }
289    }
290    #endregion
291
292    #region Job Methods
293    public DT.Job GetJob(Guid id) {
294      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
295      AuthorizationManager.AuthorizeForJob(id, DT.Permission.Read);
296      var pm = PersistenceManager;
297      using (new PerformanceLogger("GetJob")) {
298        var jobDao = pm.JobDao;
299        var jobPermissionDao = pm.JobPermissionDao;
300        var taskDao = pm.TaskDao;
301        var currentUserId = UserManager.CurrentUserId;
302        return pm.UseTransaction(() => {
303          var job = jobDao.GetById(id).ToDto();
304          if (job != null) {
305            var statistics = taskDao.GetByJobId(job.Id)
306              .GroupBy(x => x.JobId)
307              .Select(x => new {
308                TotalCount = x.Count(),
309                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
310                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
311              }).FirstOrDefault();
312            if (statistics != null) {
313              job.JobCount = statistics.TotalCount;
314              job.CalculatingCount = statistics.CalculatingCount;
315              job.FinishedCount = statistics.FinishedCount;
316            }
317            job.OwnerUsername = UserManager.GetUserNameById(job.OwnerUserId);
318            if (currentUserId == job.OwnerUserId) {
319              job.Permission = Permission.Full;
320            } else {
321              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
322              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
323            }
324          }
325          return job;
326        });
327      }
328    }
329
330    public IEnumerable<DT.Job> GetJobs() {
331      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
332      var pm = PersistenceManager;
333      using (new PerformanceLogger("GetJobs")) {
334        var jobDao = pm.JobDao;
335        var jobPermissionDao = pm.JobPermissionDao;
336        var taskDao = pm.TaskDao;
337        var currentUserId = UserManager.CurrentUserId;
338        return pm.UseTransaction(() => {
339          var jobs = jobDao.GetAll()
340            .Where(x => x.OwnerUserId == currentUserId
341                     || x.JobPermissions.Count(y => y.Permission != DA.Permission.NotAllowed
342                                                 && y.GrantedUserId == currentUserId) > 0)
343            .Select(x => x.ToDto())
344            .ToList();
345          var statistics = taskDao.GetAll()
346              .GroupBy(x => x.JobId)
347              .Select(x => new {
348                x.Key,
349                TotalCount = x.Count(),
350                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
351                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
352              })
353              .ToList();
354          foreach (var job in jobs) {
355            var statistic = statistics.FirstOrDefault(x => x.Key == job.Id);
356            if (statistic != null) {
357              job.JobCount = statistic.TotalCount;
358              job.CalculatingCount = statistic.CalculatingCount;
359              job.FinishedCount = statistic.FinishedCount;
360            }
361            job.OwnerUsername = UserManager.GetUserNameById(job.OwnerUserId);
362            if (currentUserId == job.OwnerUserId) {
363              job.Permission = Permission.Full;
364            } else {
365              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
366              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
367            }
368          }
369          return jobs;
370        });
371      }
372    }
373
374    public Guid AddJob(DT.Job jobDto) {
375      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
376      var pm = PersistenceManager;
377      using (new PerformanceLogger("AddJob")) {
378        var jobDao = pm.JobDao;
379        var userPriorityDao = pm.UserPriorityDao;
380        return pm.UseTransaction(() => {
381          jobDto.OwnerUserId = UserManager.CurrentUserId;
382          jobDto.DateCreated = DateTime.Now;
383          var job = jobDao.Save(jobDto.ToEntity());
384          if (userPriorityDao.GetById(jobDto.OwnerUserId) == null) {
385            userPriorityDao.Save(new DA.UserPriority {
386              UserId = jobDto.OwnerUserId,
387              DateEnqueued = jobDto.DateCreated
388            });
389          }
390          pm.SubmitChanges();
391          return job.JobId;
392        });
393      }
394    }
395
396    public void UpdateJob(DT.Job jobDto) {
397      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
398      AuthorizationManager.AuthorizeForJob(jobDto.Id, DT.Permission.Full);
399      var pm = PersistenceManager;
400      using (new PerformanceLogger("UpdateJob")) {
401        bool exists = true;
402        var jobDao = pm.JobDao;
403        pm.UseTransaction(() => {
404          var job = jobDao.GetById(jobDto.Id);
405          if (job == null) {
406            exists = false;
407            job = new DA.Job();
408          }
409          jobDto.CopyToEntity(job);
410          if (!exists) {
411            jobDao.Save(job);
412          }
413          pm.SubmitChanges();
414        });
415      }
416    }
417
418    public void DeleteJob(Guid jobId) {
419      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
420      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
421      var pm = PersistenceManager;
422      using (new PerformanceLogger("DeleteJob")) {
423        var jobDao = pm.JobDao;
424        pm.UseTransaction(() => {
425          // child task will be deleted by db-trigger
426          jobDao.Delete(jobId);
427          pm.SubmitChanges();
428        });
429      }
430    }
431    #endregion
432
433    #region JobPermission Methods
434    public void GrantPermission(Guid jobId, Guid grantedUserId, DT.Permission permission) {
435      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
436      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
437      var pm = PersistenceManager;
438      using (new PerformanceLogger("GrantPermission")) {
439        var jobPermissionDao = pm.JobPermissionDao;
440        var currentUserId = UserManager.CurrentUserId;
441        pm.UseTransaction(() => {
442          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, permission.ToEntity());
443          pm.SubmitChanges();
444        });
445      }
446    }
447
448    public void RevokePermission(Guid jobId, Guid grantedUserId) {
449      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
450      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
451      var pm = PersistenceManager;
452      using (new PerformanceLogger("RevokePermission")) {
453        var jobPermissionDao = pm.JobPermissionDao;
454        var currentUserId = UserManager.CurrentUserId;
455        pm.UseTransaction(() => {
456          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, DA.Permission.NotAllowed);
457          pm.SubmitChanges();
458        });
459      }
460    }
461
462    public IEnumerable<JobPermission> GetJobPermissions(Guid jobId) {
463      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
464      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
465      var pm = PersistenceManager;
466      using (new PerformanceLogger("GetJobPermissions")) {
467        var jobPermissionDao = pm.JobPermissionDao;
468        return pm.UseTransaction(() => jobPermissionDao.GetByJobId(jobId)
469          .Select(x => x.ToDto())
470          .ToList()
471        );
472      }
473    }
474
475    // BackwardsCompatibility3.3
476    #region Backwards compatible code, remove with 3.4
477    public bool IsAllowedPrivileged() {
478      return true;
479    }
480    #endregion
481    #endregion
482
483    #region Login Methods
484    public void Hello(DT.Slave slaveInfo) {
485      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
486      if (UserManager.CurrentUser.UserName != "hiveslave") {
487        slaveInfo.OwnerUserId = UserManager.CurrentUserId;
488      }
489      var pm = PersistenceManager;
490      using (new PerformanceLogger("Hello")) {
491        var slaveDao = pm.SlaveDao;
492        pm.UseTransaction(() => {
493          var slave = slaveDao.GetById(slaveInfo.Id);
494          if (slave == null) {
495            slaveDao.Save(slaveInfo.ToEntity());
496          } else {
497            bool oldIsAllowedToCalculate = slave.IsAllowedToCalculate;
498            Guid? oldParentResourceId = slave.ParentResourceId;
499            bool? oldIsDisposable = slave.IsDisposable;
500            slaveInfo.CopyToEntity(slave);
501            slave.IsAllowedToCalculate = oldIsAllowedToCalculate;
502            slave.ParentResourceId = oldParentResourceId;
503            slave.IsDisposable = oldIsDisposable;
504            slave.LastHeartbeat = DateTime.Now;
505            slave.SlaveState = DA.SlaveState.Idle;
506          }
507          pm.SubmitChanges();
508        });
509      }
510    }
511
512    public void GoodBye(Guid slaveId) {
513      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
514      var pm = PersistenceManager;
515      using (new PerformanceLogger("GoodBye")) {
516        var slaveDao = pm.SlaveDao;
517        pm.UseTransaction(() => {
518          var slave = slaveDao.GetById(slaveId);
519          if (slave != null) {
520            slave.SlaveState = DA.SlaveState.Offline;
521            pm.SubmitChanges();
522          }
523        });
524      }
525    }
526    #endregion
527
528    #region Heartbeat Methods
529    public List<MessageContainer> Heartbeat(DT.Heartbeat heartbeat) {
530      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
531      List<MessageContainer> result = new List<MessageContainer>();
532      try {
533        using (new PerformanceLogger("ProcessHeartbeat")) {
534          result = HeartbeatManager.ProcessHeartbeat(heartbeat);
535        }
536      }
537      catch (Exception ex) {
538        DA.LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("Exception processing Heartbeat: {0}", ex));
539      }
540      if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
541        TriggerEventManager(false);
542      }
543      return result;
544    }
545    #endregion
546
547    #region Plugin Methods
548    public DT.Plugin GetPlugin(Guid pluginId) {
549      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
550      var pm = PersistenceManager;
551      using (new PerformanceLogger("GetPlugin")) {
552        var pluginDao = pm.PluginDao;
553        return pm.UseTransaction(() => pluginDao.GetById(pluginId).ToDto());
554      }
555    }
556
557    public Guid AddPlugin(DT.Plugin plugin, List<DT.PluginData> pluginData) {
558      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
559      var pm = PersistenceManager;
560      using (new PerformanceLogger("AddPlugin")) {
561        var pluginDao = pm.PluginDao;
562        plugin.UserId = UserManager.CurrentUserId;
563        plugin.DateCreated = DateTime.Now;
564        return pm.UseTransaction(() => {
565          var pluginEntity = pluginDao.GetByHash(plugin.Hash).SingleOrDefault();
566          if (pluginEntity != null) {
567            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(pluginEntity.PluginId));
568          }
569          pluginEntity = plugin.ToEntity();
570          foreach (var data in pluginData) {
571            data.PluginId = default(Guid); // real id will be assigned from linq2sql
572            pluginEntity.PluginData.Add(data.ToEntity());
573          }
574          pluginDao.Save(pluginEntity);
575          pm.SubmitChanges();
576          return pluginEntity.PluginId;
577        });
578      }
579    }
580
581    public IEnumerable<DT.Plugin> GetPlugins() {
582      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
583      var pm = PersistenceManager;
584      using (new PerformanceLogger("GetPlugins")) {
585        var pluginDao = pm.PluginDao;
586        return pm.UseTransaction(() => pluginDao.GetAll()
587          .Where(x => x.Hash != null)
588          .Select(x => x.ToDto())
589          .ToList()
590        );
591      }
592    }
593
594    public IEnumerable<DT.PluginData> GetPluginDatas(List<Guid> pluginIds) {
595      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
596      var pm = PersistenceManager;
597      using (new PerformanceLogger("GetPluginDatas")) {
598        var pluginDataDao = pm.PluginDataDao;
599        return pm.UseTransaction(() => pluginDataDao.GetAll()
600            .Where(x => pluginIds.Contains(x.PluginId))
601            .Select(x => x.ToDto())
602            .ToList()
603        );
604      }
605    }
606    #endregion
607
608    #region ResourcePermission Methods
609    public void GrantResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
610      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
611      var pm = PersistenceManager;
612      using (new PerformanceLogger("GrantResourcePermissions")) {
613        pm.UseTransaction(() => {
614          var resource = AuthorizeForResource(pm, resourceId);
615          var resourcePermissions = resource.ResourcePermissions.ToList();
616          foreach (var id in grantedUserIds) {
617            if (resourcePermissions.All(x => x.GrantedUserId != id)) {
618              resource.ResourcePermissions.Add(new DA.ResourcePermission {
619                GrantedUserId = id,
620                GrantedByUserId = UserManager.CurrentUserId
621              });
622            }
623          }
624          pm.SubmitChanges();
625        });
626      }
627    }
628
629    public void RevokeResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
630      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
631      var pm = PersistenceManager;
632      using (new PerformanceLogger("RevokeResourcePermissions")) {
633        var resourcePermissionDao = pm.ResourcePermissionDao;
634        pm.UseTransaction(() => {
635          AuthorizeForResource(pm, resourceId);
636          resourcePermissionDao.DeleteByResourceAndGrantedUserId(resourceId, grantedUserIds);
637          pm.SubmitChanges();
638        });
639      }
640    }
641
642    public IEnumerable<DT.ResourcePermission> GetResourcePermissions(Guid resourceId) {
643      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
644      var pm = PersistenceManager;
645      using (new PerformanceLogger("GetResourcePermissions")) {
646        var resourcePermissionDao = pm.ResourcePermissionDao;
647        return pm.UseTransaction(() => resourcePermissionDao.GetByResourceId(resourceId)
648          .Select(x => x.ToDto())
649          .ToList()
650        );
651      }
652    }
653    #endregion
654
655    #region Slave Methods
656    public Guid AddSlave(DT.Slave slaveDto) {
657      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
658      var pm = PersistenceManager;
659      using (new PerformanceLogger("AddSlave")) {
660        var slaveDao = pm.SlaveDao;
661        return pm.UseTransaction(() => {
662          var slave = slaveDao.Save(slaveDto.ToEntity());
663          pm.SubmitChanges();
664          return slave.ResourceId;
665        });
666      }
667    }
668
669    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
670      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
671      var pm = PersistenceManager;
672      using (new PerformanceLogger("AddSlaveGroup")) {
673        var slaveGroupDao = pm.SlaveGroupDao;
674        return pm.UseTransaction(() => {
675          if (slaveGroupDto.Id == Guid.Empty) {
676            slaveGroupDto.Id = Guid.NewGuid();
677          }
678          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
679          pm.SubmitChanges();
680          return slaveGroup.ResourceId;
681        });
682      }
683    }
684
685    public DT.Slave GetSlave(Guid slaveId) {
686      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
687      var pm = PersistenceManager;
688      using (new PerformanceLogger("GetSlave")) {
689        var slaveDao = pm.SlaveDao;
690        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
691      }
692    }
693
694    public IEnumerable<DT.Slave> GetSlaves() {
695      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
696      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
697      var pm = PersistenceManager;
698      using (new PerformanceLogger("GetSlaves")) {
699        var slaveDao = pm.SlaveDao;
700        var resourcePermissionDao = pm.ResourcePermissionDao;
701        var currentUserId = UserManager.CurrentUserId;
702        return pm.UseTransaction(() => {
703          var resourcePermissions = resourcePermissionDao.GetAll();
704          return slaveDao.GetAll().ToList()
705            .Where(x => isAdministrator
706              || x.OwnerUserId == null
707              || x.OwnerUserId == currentUserId
708              || UserManager.VerifyUser(currentUserId, resourcePermissions
709                  .Where(y => y.ResourceId == x.ResourceId)
710                  .Select(z => z.GrantedUserId)
711                  .ToList())
712              )
713            .Select(x => x.ToDto())
714            .ToList();
715        });
716      }
717    }
718
719    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
720      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
721      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
722      var pm = PersistenceManager;
723      using (new PerformanceLogger("GetSlaveGroups")) {
724        var slaveGroupDao = pm.SlaveGroupDao;
725        var resourcePermissionDao = pm.ResourcePermissionDao;
726        var currentUserId = UserManager.CurrentUserId;
727        return pm.UseTransaction(() => {
728          var resourcePermissions = resourcePermissionDao.GetAll();
729          return slaveGroupDao.GetAll().ToList()
730            .Where(x => isAdministrator
731              || x.OwnerUserId == null
732              || x.OwnerUserId == currentUserId
733              || UserManager.VerifyUser(currentUserId, resourcePermissions
734                  .Where(y => y.ResourceId == x.ResourceId)
735                  .Select(z => z.GrantedUserId)
736                  .ToList())
737              )
738            .Select(x => x.ToDto())
739            .ToList();
740        });
741      }
742    }
743
744    public void UpdateSlave(DT.Slave slaveDto) {
745      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
746      var pm = PersistenceManager;
747      using (new PerformanceLogger("UpdateSlave")) {
748        var slaveDao = pm.SlaveDao;
749        pm.UseTransaction(() => {
750          var slave = slaveDao.GetById(slaveDto.Id);
751          if (slave != null) {
752            slaveDto.CopyToEntity(slave);
753          } else {
754            slaveDao.Save(slaveDto.ToEntity());
755          }
756          pm.SubmitChanges();
757        });
758      }
759    }
760
761    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
762      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
763      var pm = PersistenceManager;
764      using (new PerformanceLogger("UpdateSlaveGroup")) {
765        var slaveGroupDao = pm.SlaveGroupDao;
766        pm.UseTransaction(() => {
767          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
768          if (slaveGroup != null) {
769            slaveGroupDto.CopyToEntity(slaveGroup);
770          } else {
771            slaveGroupDao.Save(slaveGroupDto.ToEntity());
772          }
773          pm.SubmitChanges();
774        });
775      }
776    }
777
778    public void DeleteSlave(Guid slaveId) {
779      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
780      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
781      var pm = PersistenceManager;
782      using (new PerformanceLogger("DeleteSlave")) {
783        var slaveDao = pm.SlaveDao;
784        pm.UseTransaction(() => {
785          slaveDao.Delete(slaveId);
786          pm.SubmitChanges();
787        });
788      }
789    }
790
791    public void DeleteSlaveGroup(Guid slaveGroupId) {
792      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
793      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
794      var pm = PersistenceManager;
795      using (new PerformanceLogger("DeleteSlaveGroup")) {
796        var slaveGroupDao = pm.SlaveGroupDao;
797        pm.UseTransaction(() => {
798          slaveGroupDao.Delete(slaveGroupId);
799          pm.SubmitChanges();
800        });
801      }
802    }
803
804    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
805      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
806      var pm = PersistenceManager;
807      using (new PerformanceLogger("AddResourceToGroup")) {
808        var resourceDao = pm.ResourceDao;
809        pm.UseTransaction(() => {
810          var resource = resourceDao.GetById(resourceId);
811          resource.ParentResourceId = slaveGroupId;
812          pm.SubmitChanges();
813        });
814      }
815    }
816
817    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
818      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
819      var pm = PersistenceManager;
820      using (new PerformanceLogger("RemoveResourceFromGroup")) {
821        var resourceDao = pm.ResourceDao;
822        pm.UseTransaction(() => {
823          var resource = resourceDao.GetById(resourceId);
824          resource.ParentResourceId = null;
825          pm.SubmitChanges();
826        });
827      }
828    }
829
830    public Guid GetResourceId(string resourceName) {
831      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
832      var pm = PersistenceManager;
833      using (new PerformanceLogger("GetResourceId")) {
834        var resourceDao = pm.ResourceDao;
835        return pm.UseTransaction(() => {
836          var resource = resourceDao.GetByName(resourceName);
837          return resource != null ? resource.ResourceId : Guid.Empty;
838        });
839      }
840    }
841
842    public void TriggerEventManager(bool force) {
843      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
844      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
845      bool cleanup;
846      var pm = PersistenceManager;
847      using (new PerformanceLogger("TriggerEventManager")) {
848        cleanup = false;
849        var lifecycleDao = pm.LifecycleDao;
850        pm.UseTransaction(() => {
851          var lastLifecycle = lifecycleDao.GetLastLifecycle();
852          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
853          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
854            lifecycleDao.UpdateLifecycle();
855            cleanup = true;
856            pm.SubmitChanges();
857          }
858        }, true);
859      }
860      if (cleanup) {
861        EventManager.Cleanup();
862      }
863    }
864
865    public int GetNewHeartbeatInterval(Guid slaveId) {
866      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
867      var pm = PersistenceManager;
868      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
869        var slaveDao = pm.SlaveDao;
870        return pm.UseTransaction(() => {
871          var slave = slaveDao.GetById(slaveId);
872          if (slave != null) {
873            return slave.HbInterval;
874          }
875          return -1;
876        });
877      }
878    }
879    #endregion
880
881    #region Downtime Methods
882    public Guid AddDowntime(DT.Downtime downtimeDto) {
883      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
884      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
885      var pm = PersistenceManager;
886      using (new PerformanceLogger("AddDowntime")) {
887        var downtimeDao = pm.DowntimeDao;
888        return pm.UseTransaction(() => {
889          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
890          pm.SubmitChanges();
891          return downtime.ResourceId;
892        });
893      }
894    }
895
896    public void DeleteDowntime(Guid downtimeId) {
897      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
898      var pm = PersistenceManager;
899      using (new PerformanceLogger("DeleteDowntime")) {
900        var downtimeDao = pm.DowntimeDao;
901        pm.UseTransaction(() => {
902          downtimeDao.Delete(downtimeId);
903          pm.SubmitChanges();
904        });
905      }
906    }
907
908    public void UpdateDowntime(DT.Downtime downtimeDto) {
909      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
910      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
911      var pm = PersistenceManager;
912      using (new PerformanceLogger("UpdateDowntime")) {
913        var downtimeDao = pm.DowntimeDao;
914        pm.UseTransaction(() => {
915          var downtime = downtimeDao.GetById(downtimeDto.Id);
916          if (downtime != null) {
917            downtimeDto.CopyToEntity(downtime);
918          } else {
919            downtimeDao.Save(downtimeDto.ToEntity());
920          }
921          pm.SubmitChanges();
922        });
923      }
924    }
925
926    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
927      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
928      var pm = PersistenceManager;
929      using (new PerformanceLogger("GetDowntimesForResource")) {
930        var downtimeDao = pm.DowntimeDao;
931        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
932          .Select(x => x.ToDto())
933          .ToList()
934        );
935      }
936    }
937    #endregion
938
939    #region User Methods
940    public string GetUsernameByUserId(Guid userId) {
941      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
942      var user = UserManager.GetUserById(userId);
943      return user != null ? user.UserName : null;
944    }
945
946    public Guid GetUserIdByUsername(string username) {
947      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
948      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
949      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
950    }
951    #endregion
952
953    #region UserPriorities Methods
954    public IEnumerable<DT.UserPriority> GetUserPriorities() {
955      var pm = PersistenceManager;
956      using (new PerformanceLogger("GetUserPriorities")) {
957        var userPriorityDao = pm.UserPriorityDao;
958        return pm.UseTransaction(() => userPriorityDao.GetAll()
959          .Select(x => x.ToDto())
960          .ToList()
961        );
962      }
963    }
964    #endregion
965
966    #region Private Helper Methods
967    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
968      var stateLogDao = pm.StateLogDao;
969      var taskStateEntity = taskState.ToEntity();
970
971      if (task.State == DA.TaskState.Transferring && taskStateEntity == DA.TaskState.Paused && task.Command == null) {
972        // slave paused and uploaded the task (no user-command) -> set waiting.
973        taskStateEntity = DA.TaskState.Waiting;
974      }
975
976      stateLogDao.Save(new DA.StateLog {
977        State = taskStateEntity,
978        DateTime = DateTime.Now,
979        TaskId = task.TaskId,
980        UserId = userId,
981        SlaveId = slaveId,
982        Exception = exception
983      });
984
985      task.State = taskStateEntity;
986
987      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
988          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
989          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
990        task.Command = null;
991      }
992    }
993
994    private DA.Resource AuthorizeForResource(IPersistenceManager pm, Guid resourceId) {
995      var resourceDao = pm.ResourceDao;
996      var resource = resourceDao.GetById(resourceId);
997      if (resource == null) throw new SecurityException("Not authorized");
998      if (resource.OwnerUserId != UserManager.CurrentUserId
999          && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
1000        throw new SecurityException("Not authorized");
1001      }
1002      return resource;
1003    }
1004    #endregion
1005  }
1006}
Note: See TracBrowser for help on using the repository browser.