source: branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 12861

Last change on this file since 12861 was 12861, checked in by ascheibe, 7 years ago

#2388 removed old code and switched to new code

File size: 39.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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          }
266          UpdateTaskState(pm, task, DT.TaskState.Paused, null, null, string.Empty);
267          pm.SubmitChanges();
268        });
269      }
270    }
271
272    public void RestartTask(Guid taskId) {
273      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
274      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
275      var pm = PersistenceManager;
276      using (new PerformanceLogger("RestartTask")) {
277        var taskDao = pm.TaskDao;
278        pm.UseTransaction(() => {
279          var task = taskDao.GetById(taskId);
280          task.Command = null;
281          UpdateTaskState(pm, task, DT.TaskState.Waiting, null, UserManager.CurrentUserId, string.Empty);
282          pm.SubmitChanges();
283        });
284      }
285    }
286    #endregion
287
288    #region Job Methods
289    public DT.Job GetJob(Guid id) {
290      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
291      AuthorizationManager.AuthorizeForJob(id, DT.Permission.Read);
292      var pm = PersistenceManager;
293      using (new PerformanceLogger("GetJob")) {
294        var jobDao = pm.JobDao;
295        var jobPermissionDao = pm.JobPermissionDao;
296        var taskDao = pm.TaskDao;
297        var currentUserId = UserManager.CurrentUserId;
298        return pm.UseTransaction(() => {
299          var job = jobDao.GetById(id).ToDto();
300          if (job != null) {
301            var statistics = taskDao.GetByJobId(job.Id)
302              .GroupBy(x => x.JobId)
303              .Select(x => new {
304                TotalCount = x.Count(),
305                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
306                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
307              }).FirstOrDefault();
308            if (statistics != null) {
309              job.JobCount = statistics.TotalCount;
310              job.CalculatingCount = statistics.CalculatingCount;
311              job.FinishedCount = statistics.FinishedCount;
312            }
313            job.OwnerUsername = UserManager.GetUserById(job.OwnerUserId).UserName;
314            if (currentUserId == job.OwnerUserId) {
315              job.Permission = Permission.Full;
316            } else {
317              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
318              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
319            }
320          }
321          return job;
322        });
323      }
324    }
325
326    public IEnumerable<DT.Job> GetJobs() {
327      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
328      var pm = PersistenceManager;
329      using (new PerformanceLogger("GetJobs")) {
330        var jobDao = pm.JobDao;
331        var jobPermissionDao = pm.JobPermissionDao;
332        var taskDao = pm.TaskDao;
333        var currentUserId = UserManager.CurrentUserId;
334        return pm.UseTransaction(() => {
335          var jobs = jobDao.GetAll()
336            .Where(x => x.OwnerUserId == currentUserId
337                     || x.JobPermissions.Count(y => y.Permission != DA.Permission.NotAllowed
338                                                 && y.GrantedUserId == currentUserId) > 0)
339            .Select(x => x.ToDto())
340            .ToList();
341          var statistics = taskDao.GetAll()
342              .GroupBy(x => x.JobId)
343              .Select(x => new {
344                x.Key,
345                TotalCount = x.Count(),
346                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
347                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
348              })
349              .ToList();
350          foreach (var job in jobs) {
351            var statistic = statistics.FirstOrDefault(x => x.Key == job.Id);
352            if (statistic != null) {
353              job.JobCount = statistic.TotalCount;
354              job.CalculatingCount = statistic.CalculatingCount;
355              job.FinishedCount = statistic.FinishedCount;
356            }
357            job.OwnerUsername = UserManager.GetUserById(job.OwnerUserId).UserName;
358            if (currentUserId == job.OwnerUserId) {
359              job.Permission = Permission.Full;
360            } else {
361              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
362              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
363            }
364          }
365          return jobs;
366        });
367      }
368    }
369
370    public Guid AddJob(DT.Job jobDto) {
371      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
372      var pm = PersistenceManager;
373      using (new PerformanceLogger("AddJob")) {
374        var jobDao = pm.JobDao;
375        var userPriorityDao = pm.UserPriorityDao;
376        return pm.UseTransaction(() => {
377          jobDto.OwnerUserId = UserManager.CurrentUserId;
378          jobDto.DateCreated = DateTime.Now;
379          var job = jobDao.Save(jobDto.ToEntity());
380          if (userPriorityDao.GetById(jobDto.OwnerUserId) == null) {
381            userPriorityDao.Save(new DA.UserPriority {
382              UserId = jobDto.OwnerUserId,
383              DateEnqueued = jobDto.DateCreated
384            });
385          }
386          pm.SubmitChanges();
387          return job.JobId;
388        });
389      }
390    }
391
392    public void UpdateJob(DT.Job jobDto) {
393      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
394      AuthorizationManager.AuthorizeForJob(jobDto.Id, DT.Permission.Full);
395      var pm = PersistenceManager;
396      using (new PerformanceLogger("UpdateJob")) {
397        bool exists = true;
398        var jobDao = pm.JobDao;
399        pm.UseTransaction(() => {
400          var job = jobDao.GetById(jobDto.Id);
401          if (job == null) {
402            exists = false;
403            job = new DA.Job();
404          }
405          jobDto.CopyToEntity(job);
406          if (!exists) {
407            jobDao.Save(job);
408          }
409          pm.SubmitChanges();
410        });
411      }
412    }
413
414    public void DeleteJob(Guid jobId) {
415      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
416      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
417      var pm = PersistenceManager;
418      using (new PerformanceLogger("DeleteJob")) {
419        var jobDao = pm.JobDao;
420        pm.UseTransaction(() => {
421          // child task will be deleted by db-trigger
422          jobDao.Delete(jobId);
423          pm.SubmitChanges();
424        });
425      }
426    }
427    #endregion
428
429    #region JobPermission Methods
430    public void GrantPermission(Guid jobId, Guid grantedUserId, DT.Permission permission) {
431      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
432      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
433      var pm = PersistenceManager;
434      using (new PerformanceLogger("GrantPermission")) {
435        var jobPermissionDao = pm.JobPermissionDao;
436        var currentUserId = UserManager.CurrentUserId;
437        pm.UseTransaction(() => {
438          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, permission.ToEntity());
439          pm.SubmitChanges();
440        });
441      }
442    }
443
444    public void RevokePermission(Guid jobId, Guid grantedUserId) {
445      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
446      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
447      var pm = PersistenceManager;
448      using (new PerformanceLogger("RevokePermission")) {
449        var jobPermissionDao = pm.JobPermissionDao;
450        var currentUserId = UserManager.CurrentUserId;
451        pm.UseTransaction(() => {
452          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, DA.Permission.NotAllowed);
453          pm.SubmitChanges();
454        });
455      }
456    }
457
458    public IEnumerable<JobPermission> GetJobPermissions(Guid jobId) {
459      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
460      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
461      var pm = PersistenceManager;
462      using (new PerformanceLogger("GetJobPermissions")) {
463        var jobPermissionDao = pm.JobPermissionDao;
464        return pm.UseTransaction(() => jobPermissionDao.GetByJobId(jobId)
465          .Select(x => x.ToDto())
466          .ToList()
467        );
468      }
469    }
470
471    public bool IsAllowedPrivileged() {
472      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
473      return RoleVerifier.IsInRole(HiveRoles.IsAllowedPrivileged);
474    }
475    #endregion
476
477    #region Login Methods
478    public void Hello(DT.Slave slaveInfo) {
479      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
480      if (UserManager.CurrentUser.UserName != "hiveslave") {
481        slaveInfo.OwnerUserId = UserManager.CurrentUserId;
482      }
483      var pm = PersistenceManager;
484      using (new PerformanceLogger("Hello")) {
485        var slaveDao = pm.SlaveDao;
486        pm.UseTransaction(() => {
487          var slave = slaveDao.GetById(slaveInfo.Id);
488          if (slave == null) {
489            slaveDao.Save(slaveInfo.ToEntity());
490          } else {
491            bool oldIsAllowedToCalculate = slave.IsAllowedToCalculate;
492            Guid? oldParentResourceId = slave.ParentResourceId;
493            slaveInfo.CopyToEntity(slave);
494            slave.IsAllowedToCalculate = oldIsAllowedToCalculate;
495            slave.ParentResourceId = oldParentResourceId;
496            slave.LastHeartbeat = DateTime.Now;
497            slave.SlaveState = DA.SlaveState.Idle;
498          }
499          pm.SubmitChanges();
500        });
501      }
502    }
503
504    public void GoodBye(Guid slaveId) {
505      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
506      var pm = PersistenceManager;
507      using (new PerformanceLogger("GoodBye")) {
508        var slaveDao = pm.SlaveDao;
509        pm.UseTransaction(() => {
510          var slave = slaveDao.GetById(slaveId);
511          if (slave != null) {
512            slave.SlaveState = DA.SlaveState.Offline;
513            pm.SubmitChanges();
514          }
515        });
516      }
517    }
518    #endregion
519
520    #region Heartbeat Methods
521    public List<MessageContainer> Heartbeat(DT.Heartbeat heartbeat) {
522      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
523      List<MessageContainer> result = new List<MessageContainer>();
524      try {
525        using (new PerformanceLogger("ProcessHeartbeat")) {
526          result = HeartbeatManager.ProcessHeartbeat(heartbeat);
527        }
528      }
529      catch (Exception ex) {
530        DA.LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("Exception processing Heartbeat: {0}", ex));
531      }
532      if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
533        TriggerEventManager(false);
534      }
535      return result;
536    }
537    #endregion
538
539    #region Plugin Methods
540    public DT.Plugin GetPlugin(Guid pluginId) {
541      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
542      var pm = PersistenceManager;
543      using (new PerformanceLogger("GetPlugin")) {
544        var pluginDao = pm.PluginDao;
545        return pm.UseTransaction(() => pluginDao.GetById(pluginId).ToDto());
546      }
547    }
548
549    public Guid AddPlugin(DT.Plugin plugin, List<DT.PluginData> pluginData) {
550      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
551      var pm = PersistenceManager;
552      using (new PerformanceLogger("AddPlugin")) {
553        var pluginDao = pm.PluginDao;
554        plugin.UserId = UserManager.CurrentUserId;
555        plugin.DateCreated = DateTime.Now;
556        return pm.UseTransaction(() => {
557          var pluginEntity = pluginDao.GetByHash(plugin.Hash).SingleOrDefault();
558          if (pluginEntity != null) {
559            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(pluginEntity.PluginId));
560          }
561          pluginEntity = plugin.ToEntity();
562          foreach (var data in pluginData) {
563            data.PluginId = default(Guid); // real id will be assigned from linq2sql
564            pluginEntity.PluginData.Add(data.ToEntity());
565          }
566          pluginDao.Save(pluginEntity);
567          pm.SubmitChanges();
568          return pluginEntity.PluginId;
569        });
570      }
571    }
572
573    public IEnumerable<DT.Plugin> GetPlugins() {
574      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
575      var pm = PersistenceManager;
576      using (new PerformanceLogger("GetPlugins")) {
577        var pluginDao = pm.PluginDao;
578        return pm.UseTransaction(() => pluginDao.GetAll()
579          .Where(x => x.Hash != null)
580          .Select(x => x.ToDto())
581          .ToList()
582        );
583      }
584    }
585
586    public IEnumerable<DT.PluginData> GetPluginDatas(List<Guid> pluginIds) {
587      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
588      var pm = PersistenceManager;
589      using (new PerformanceLogger("GetPluginDatas")) {
590        var pluginDataDao = pm.PluginDataDao;
591        return pm.UseTransaction(() => pluginDataDao.GetAll()
592            .Where(x => pluginIds.Contains(x.PluginId))
593            .Select(x => x.ToDto())
594            .ToList()
595        );
596      }
597    }
598    #endregion
599
600    #region ResourcePermission Methods
601    public void GrantResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
602      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
603      var pm = PersistenceManager;
604      using (new PerformanceLogger("GrantResourcePermissions")) {
605        pm.UseTransaction(() => {
606          var resource = AuthorizeForResource(pm, resourceId);
607          var resourcePermissions = resource.ResourcePermissions.ToList();
608          foreach (var id in grantedUserIds) {
609            if (resourcePermissions.All(x => x.GrantedUserId != id)) {
610              resource.ResourcePermissions.Add(new DA.ResourcePermission {
611                GrantedUserId = id,
612                GrantedByUserId = UserManager.CurrentUserId
613              });
614            }
615          }
616          pm.SubmitChanges();
617        });
618      }
619    }
620
621    public void RevokeResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
622      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
623      var pm = PersistenceManager;
624      using (new PerformanceLogger("RevokeResourcePermissions")) {
625        var resourcePermissionDao = pm.ResourcePermissionDao;
626        pm.UseTransaction(() => {
627          AuthorizeForResource(pm, resourceId);
628          resourcePermissionDao.DeleteByResourceAndGrantedUserId(resourceId, grantedUserIds);
629        });
630      }
631    }
632
633    public IEnumerable<DT.ResourcePermission> GetResourcePermissions(Guid resourceId) {
634      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
635      var pm = PersistenceManager;
636      using (new PerformanceLogger("GetResourcePermissions")) {
637        var resourcePermissionDao = pm.ResourcePermissionDao;
638        return pm.UseTransaction(() => resourcePermissionDao.GetByResourceId(resourceId)
639          .Select(x => x.ToDto())
640          .ToList()
641        );
642      }
643    }
644    #endregion
645
646    #region Slave Methods
647    public Guid AddSlave(DT.Slave slaveDto) {
648      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
649      var pm = PersistenceManager;
650      using (new PerformanceLogger("AddSlave")) {
651        var slaveDao = pm.SlaveDao;
652        return pm.UseTransaction(() => {
653          var slave = slaveDao.Save(slaveDto.ToEntity());
654          pm.SubmitChanges();
655          return slave.ResourceId;
656        });
657      }
658    }
659
660    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
661      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
662      var pm = PersistenceManager;
663      using (new PerformanceLogger("AddSlaveGroup")) {
664        var slaveGroupDao = pm.SlaveGroupDao;
665        return pm.UseTransaction(() => {
666          if (slaveGroupDto.Id == Guid.Empty) {
667            slaveGroupDto.Id = Guid.NewGuid();
668          }
669          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
670          pm.SubmitChanges();
671          return slaveGroup.ResourceId;
672        });
673      }
674    }
675
676    public DT.Slave GetSlave(Guid slaveId) {
677      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
678      var pm = PersistenceManager;
679      using (new PerformanceLogger("GetSlave")) {
680        var slaveDao = pm.SlaveDao;
681        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
682      }
683    }
684
685    public IEnumerable<DT.Slave> GetSlaves() {
686      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
687      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
688      var pm = PersistenceManager;
689      using (new PerformanceLogger("GetSlaves")) {
690        var slaveDao = pm.SlaveDao;
691        var resourcePermissionDao = pm.ResourcePermissionDao;
692        var currentUserId = UserManager.CurrentUserId;
693        return pm.UseTransaction(() => {
694          var resourcePermissions = resourcePermissionDao.GetAll();
695          return slaveDao.GetAll()
696            .Where(x => isAdministrator
697              || x.OwnerUserId == null
698              || x.OwnerUserId == currentUserId
699              || UserManager.VerifyUser(currentUserId, resourcePermissions
700                  .Where(y => y.ResourceId == x.ResourceId)
701                  .Select(z => z.GrantedUserId)
702                  .ToList())
703              )
704            .Select(x => x.ToDto())
705            .ToList();
706        });
707      }
708    }
709
710    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
711      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
712      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
713      var pm = PersistenceManager;
714      using (new PerformanceLogger("GetSlaveGroups")) {
715        var slaveGroupDao = pm.SlaveGroupDao;
716        var resourcePermissionDao = pm.ResourcePermissionDao;
717        var currentUserId = UserManager.CurrentUserId;
718        return pm.UseTransaction(() => {
719          var resourcePermissions = resourcePermissionDao.GetAll();
720          return slaveGroupDao.GetAll()
721            .Where(x => isAdministrator
722              || x.OwnerUserId == null
723              || x.OwnerUserId == currentUserId
724              || UserManager.VerifyUser(currentUserId, resourcePermissions
725                  .Where(y => y.ResourceId == x.ResourceId)
726                  .Select(z => z.GrantedUserId)
727                  .ToList())
728              )
729            .Select(x => x.ToDto())
730            .ToList();
731        });
732      }
733    }
734
735    public void UpdateSlave(DT.Slave slaveDto) {
736      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
737      var pm = PersistenceManager;
738      using (new PerformanceLogger("UpdateSlave")) {
739        var slaveDao = pm.SlaveDao;
740        pm.UseTransaction(() => {
741          var slave = slaveDao.GetById(slaveDto.Id);
742          if (slave != null) {
743            slaveDto.CopyToEntity(slave);
744          } else {
745            slaveDao.Save(slaveDto.ToEntity());
746          }
747          pm.SubmitChanges();
748        });
749      }
750    }
751
752    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
753      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
754      var pm = PersistenceManager;
755      using (new PerformanceLogger("UpdateSlaveGroup")) {
756        var slaveGroupDao = pm.SlaveGroupDao;
757        pm.UseTransaction(() => {
758          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
759          if (slaveGroup != null) {
760            slaveGroupDto.CopyToEntity(slaveGroup);
761          } else {
762            slaveGroupDao.Save(slaveGroupDto.ToEntity());
763          }
764          pm.SubmitChanges();
765        });
766      }
767    }
768
769    public void DeleteSlave(Guid slaveId) {
770      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
771      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
772      var pm = PersistenceManager;
773      using (new PerformanceLogger("DeleteSlave")) {
774        var slaveDao = pm.SlaveDao;
775        pm.UseTransaction(() => {
776          slaveDao.Delete(slaveId);
777        });
778      }
779    }
780
781    public void DeleteSlaveGroup(Guid slaveGroupId) {
782      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
783      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
784      var pm = PersistenceManager;
785      using (new PerformanceLogger("DeleteSlaveGroup")) {
786        var slaveGroupDao = pm.SlaveGroupDao;
787        pm.UseTransaction(() => {
788          slaveGroupDao.Delete(slaveGroupId);
789        });
790      }
791    }
792
793    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
794      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
795      var pm = PersistenceManager;
796      using (new PerformanceLogger("AddResourceToGroup")) {
797        var resourceDao = pm.ResourceDao;
798        pm.UseTransaction(() => {
799          var resource = resourceDao.GetById(resourceId);
800          resource.ParentResourceId = slaveGroupId;
801          pm.SubmitChanges();
802        });
803      }
804    }
805
806    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
807      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
808      var pm = PersistenceManager;
809      using (new PerformanceLogger("RemoveResourceFromGroup")) {
810        var resourceDao = pm.ResourceDao;
811        pm.UseTransaction(() => {
812          var resource = resourceDao.GetById(resourceId);
813          resource.ParentResourceId = null;
814          pm.SubmitChanges();
815        });
816      }
817    }
818
819    public Guid GetResourceId(string resourceName) {
820      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
821      var pm = PersistenceManager;
822      using (new PerformanceLogger("GetResourceId")) {
823        var resourceDao = pm.ResourceDao;
824        return pm.UseTransaction(() => {
825          var resource = resourceDao.GetByName(resourceName);
826          return resource != null ? resource.ResourceId : Guid.Empty;
827        });
828      }
829    }
830
831    public void TriggerEventManager(bool force) {
832      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
833      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
834      bool cleanup;
835      var pm = PersistenceManager;
836      using (new PerformanceLogger("TriggerEventManager")) {
837        cleanup = false;
838        var lifecycleDao = pm.LifecycleDao;
839        pm.UseTransaction(() => {
840          var lastLifecycle = lifecycleDao.GetLastLifecycle();
841          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
842          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
843            lifecycleDao.UpdateLifecycle();
844            cleanup = true;
845            pm.SubmitChanges();
846          }
847        }, true);
848      }
849      if (cleanup) {
850        EventManager.Cleanup();
851      }
852    }
853
854    public int GetNewHeartbeatInterval(Guid slaveId) {
855      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
856      var pm = PersistenceManager;
857      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
858        var slaveDao = pm.SlaveDao;
859        return pm.UseTransaction(() => {
860          var slave = slaveDao.GetById(slaveId);
861          if (slave != null) {
862            return slave.HbInterval;
863          }
864          return -1;
865        });
866      }
867    }
868    #endregion
869
870    #region Downtime Methods
871    public Guid AddDowntime(DT.Downtime downtimeDto) {
872      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
873      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
874      var pm = PersistenceManager;
875      using (new PerformanceLogger("AddDowntime")) {
876        var downtimeDao = pm.DowntimeDao;
877        return pm.UseTransaction(() => {
878          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
879          pm.SubmitChanges();
880          return downtime.ResourceId;
881        });
882      }
883    }
884
885    public void DeleteDowntime(Guid downtimeId) {
886      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
887      var pm = PersistenceManager;
888      using (new PerformanceLogger("DeleteDowntime")) {
889        var downtimeDao = pm.DowntimeDao;
890        pm.UseTransaction(() => {
891          downtimeDao.Delete(downtimeId);
892          pm.SubmitChanges();
893        });
894      }
895    }
896
897    public void UpdateDowntime(DT.Downtime downtimeDto) {
898      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
899      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
900      var pm = PersistenceManager;
901      using (new PerformanceLogger("UpdateDowntime")) {
902        var downtimeDao = pm.DowntimeDao;
903        pm.UseTransaction(() => {
904          var downtime = downtimeDao.GetById(downtimeDto.Id);
905          if (downtime != null) {
906            downtimeDto.CopyToEntity(downtime);
907          } else {
908            downtimeDao.Save(downtimeDto.ToEntity());
909          }
910          pm.SubmitChanges();
911        });
912      }
913    }
914
915    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
916      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
917      var pm = PersistenceManager;
918      using (new PerformanceLogger("GetDowntimesForResource")) {
919        var downtimeDao = pm.DowntimeDao;
920        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
921          .Select(x => x.ToDto())
922          .ToList()
923        );
924      }
925    }
926    #endregion
927
928    #region User Methods
929    public string GetUsernameByUserId(Guid userId) {
930      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
931      var user = UserManager.GetUserById(userId);
932      return user != null ? user.UserName : null;
933    }
934
935    public Guid GetUserIdByUsername(string username) {
936      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
937      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
938      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
939    }
940    #endregion
941
942    #region UserPriorities Methods
943    public IEnumerable<DT.UserPriority> GetUserPriorities() {
944      var pm = PersistenceManager;
945      using (new PerformanceLogger("GetUserPriorities")) {
946        var userPriorityDao = pm.UserPriorityDao;
947        return pm.UseTransaction(() => userPriorityDao.GetAll()
948          .Select(x => x.ToDto())
949          .ToList()
950        );
951      }
952    }
953    #endregion
954
955    #region Private Helper Methods
956    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
957      var stateLogDao = pm.StateLogDao;
958      var taskStateEntity = taskState.ToEntity();
959      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
960          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
961          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
962        task.Command = null;
963      } else if (taskStateEntity == DA.TaskState.Paused && task.Command != null) {
964        // slave paused and uploaded the task (no user-command) -> set waiting.
965        taskStateEntity = DA.TaskState.Waiting;
966      }
967      stateLogDao.Save(new DA.StateLog {
968        State = taskStateEntity,
969        DateTime = DateTime.Now,
970        TaskId = task.TaskId,
971        UserId = userId,
972        SlaveId = slaveId,
973        Exception = exception
974      });
975      task.State = taskStateEntity;
976    }
977
978    private DA.Resource AuthorizeForResource(IPersistenceManager pm, Guid resourceId) {
979      var resourceDao = pm.ResourceDao;
980      var resource = resourceDao.GetById(resourceId);
981      if (resource == null) throw new SecurityException("Not authorized");
982      if (resource.OwnerUserId != UserManager.CurrentUserId
983          && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
984        throw new SecurityException("Not authorized");
985      }
986      return resource;
987    }
988    #endregion
989  }
990}
Note: See TracBrowser for help on using the repository browser.