source: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 12932

Last change on this file since 12932 was 12932, checked in by ascheibe, 6 years ago

#2388 fixed problem with not existing users when downloading shared jobs

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.GetUserNameById(job.OwnerUserId);
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.GetUserNameById(job.OwnerUserId);
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    // BackwardsCompatibility3.3
472    #region Backwards compatible code, remove with 3.4
473    public bool IsAllowedPrivileged() {
474      return true;
475    }
476    #endregion
477    #endregion
478
479    #region Login Methods
480    public void Hello(DT.Slave slaveInfo) {
481      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
482      if (UserManager.CurrentUser.UserName != "hiveslave") {
483        slaveInfo.OwnerUserId = UserManager.CurrentUserId;
484      }
485      var pm = PersistenceManager;
486      using (new PerformanceLogger("Hello")) {
487        var slaveDao = pm.SlaveDao;
488        pm.UseTransaction(() => {
489          var slave = slaveDao.GetById(slaveInfo.Id);
490          if (slave == null) {
491            slaveDao.Save(slaveInfo.ToEntity());
492          } else {
493            bool oldIsAllowedToCalculate = slave.IsAllowedToCalculate;
494            Guid? oldParentResourceId = slave.ParentResourceId;
495            slaveInfo.CopyToEntity(slave);
496            slave.IsAllowedToCalculate = oldIsAllowedToCalculate;
497            slave.ParentResourceId = oldParentResourceId;
498            slave.LastHeartbeat = DateTime.Now;
499            slave.SlaveState = DA.SlaveState.Idle;
500          }
501          pm.SubmitChanges();
502        });
503      }
504    }
505
506    public void GoodBye(Guid slaveId) {
507      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
508      var pm = PersistenceManager;
509      using (new PerformanceLogger("GoodBye")) {
510        var slaveDao = pm.SlaveDao;
511        pm.UseTransaction(() => {
512          var slave = slaveDao.GetById(slaveId);
513          if (slave != null) {
514            slave.SlaveState = DA.SlaveState.Offline;
515            pm.SubmitChanges();
516          }
517        });
518      }
519    }
520    #endregion
521
522    #region Heartbeat Methods
523    public List<MessageContainer> Heartbeat(DT.Heartbeat heartbeat) {
524      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
525      List<MessageContainer> result = new List<MessageContainer>();
526      try {
527        using (new PerformanceLogger("ProcessHeartbeat")) {
528          result = HeartbeatManager.ProcessHeartbeat(heartbeat);
529        }
530      }
531      catch (Exception ex) {
532        DA.LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("Exception processing Heartbeat: {0}", ex));
533      }
534      if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
535        TriggerEventManager(false);
536      }
537      return result;
538    }
539    #endregion
540
541    #region Plugin Methods
542    public DT.Plugin GetPlugin(Guid pluginId) {
543      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
544      var pm = PersistenceManager;
545      using (new PerformanceLogger("GetPlugin")) {
546        var pluginDao = pm.PluginDao;
547        return pm.UseTransaction(() => pluginDao.GetById(pluginId).ToDto());
548      }
549    }
550
551    public Guid AddPlugin(DT.Plugin plugin, List<DT.PluginData> pluginData) {
552      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
553      var pm = PersistenceManager;
554      using (new PerformanceLogger("AddPlugin")) {
555        var pluginDao = pm.PluginDao;
556        plugin.UserId = UserManager.CurrentUserId;
557        plugin.DateCreated = DateTime.Now;
558        return pm.UseTransaction(() => {
559          var pluginEntity = pluginDao.GetByHash(plugin.Hash).SingleOrDefault();
560          if (pluginEntity != null) {
561            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(pluginEntity.PluginId));
562          }
563          pluginEntity = plugin.ToEntity();
564          foreach (var data in pluginData) {
565            data.PluginId = default(Guid); // real id will be assigned from linq2sql
566            pluginEntity.PluginData.Add(data.ToEntity());
567          }
568          pluginDao.Save(pluginEntity);
569          pm.SubmitChanges();
570          return pluginEntity.PluginId;
571        });
572      }
573    }
574
575    public IEnumerable<DT.Plugin> GetPlugins() {
576      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
577      var pm = PersistenceManager;
578      using (new PerformanceLogger("GetPlugins")) {
579        var pluginDao = pm.PluginDao;
580        return pm.UseTransaction(() => pluginDao.GetAll()
581          .Where(x => x.Hash != null)
582          .Select(x => x.ToDto())
583          .ToList()
584        );
585      }
586    }
587
588    public IEnumerable<DT.PluginData> GetPluginDatas(List<Guid> pluginIds) {
589      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
590      var pm = PersistenceManager;
591      using (new PerformanceLogger("GetPluginDatas")) {
592        var pluginDataDao = pm.PluginDataDao;
593        return pm.UseTransaction(() => pluginDataDao.GetAll()
594            .Where(x => pluginIds.Contains(x.PluginId))
595            .Select(x => x.ToDto())
596            .ToList()
597        );
598      }
599    }
600    #endregion
601
602    #region ResourcePermission Methods
603    public void GrantResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
604      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
605      var pm = PersistenceManager;
606      using (new PerformanceLogger("GrantResourcePermissions")) {
607        pm.UseTransaction(() => {
608          var resource = AuthorizeForResource(pm, resourceId);
609          var resourcePermissions = resource.ResourcePermissions.ToList();
610          foreach (var id in grantedUserIds) {
611            if (resourcePermissions.All(x => x.GrantedUserId != id)) {
612              resource.ResourcePermissions.Add(new DA.ResourcePermission {
613                GrantedUserId = id,
614                GrantedByUserId = UserManager.CurrentUserId
615              });
616            }
617          }
618          pm.SubmitChanges();
619        });
620      }
621    }
622
623    public void RevokeResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
624      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
625      var pm = PersistenceManager;
626      using (new PerformanceLogger("RevokeResourcePermissions")) {
627        var resourcePermissionDao = pm.ResourcePermissionDao;
628        pm.UseTransaction(() => {
629          AuthorizeForResource(pm, resourceId);
630          resourcePermissionDao.DeleteByResourceAndGrantedUserId(resourceId, grantedUserIds);
631        });
632      }
633    }
634
635    public IEnumerable<DT.ResourcePermission> GetResourcePermissions(Guid resourceId) {
636      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
637      var pm = PersistenceManager;
638      using (new PerformanceLogger("GetResourcePermissions")) {
639        var resourcePermissionDao = pm.ResourcePermissionDao;
640        return pm.UseTransaction(() => resourcePermissionDao.GetByResourceId(resourceId)
641          .Select(x => x.ToDto())
642          .ToList()
643        );
644      }
645    }
646    #endregion
647
648    #region Slave Methods
649    public Guid AddSlave(DT.Slave slaveDto) {
650      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
651      var pm = PersistenceManager;
652      using (new PerformanceLogger("AddSlave")) {
653        var slaveDao = pm.SlaveDao;
654        return pm.UseTransaction(() => {
655          var slave = slaveDao.Save(slaveDto.ToEntity());
656          pm.SubmitChanges();
657          return slave.ResourceId;
658        });
659      }
660    }
661
662    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
663      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
664      var pm = PersistenceManager;
665      using (new PerformanceLogger("AddSlaveGroup")) {
666        var slaveGroupDao = pm.SlaveGroupDao;
667        return pm.UseTransaction(() => {
668          if (slaveGroupDto.Id == Guid.Empty) {
669            slaveGroupDto.Id = Guid.NewGuid();
670          }
671          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
672          pm.SubmitChanges();
673          return slaveGroup.ResourceId;
674        });
675      }
676    }
677
678    public DT.Slave GetSlave(Guid slaveId) {
679      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
680      var pm = PersistenceManager;
681      using (new PerformanceLogger("GetSlave")) {
682        var slaveDao = pm.SlaveDao;
683        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
684      }
685    }
686
687    public IEnumerable<DT.Slave> GetSlaves() {
688      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
689      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
690      var pm = PersistenceManager;
691      using (new PerformanceLogger("GetSlaves")) {
692        var slaveDao = pm.SlaveDao;
693        var resourcePermissionDao = pm.ResourcePermissionDao;
694        var currentUserId = UserManager.CurrentUserId;
695        return pm.UseTransaction(() => {
696          var resourcePermissions = resourcePermissionDao.GetAll();
697          return slaveDao.GetAll()
698            .Where(x => isAdministrator
699              || x.OwnerUserId == null
700              || x.OwnerUserId == currentUserId
701              || UserManager.VerifyUser(currentUserId, resourcePermissions
702                  .Where(y => y.ResourceId == x.ResourceId)
703                  .Select(z => z.GrantedUserId)
704                  .ToList())
705              )
706            .Select(x => x.ToDto())
707            .ToList();
708        });
709      }
710    }
711
712    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
713      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
714      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
715      var pm = PersistenceManager;
716      using (new PerformanceLogger("GetSlaveGroups")) {
717        var slaveGroupDao = pm.SlaveGroupDao;
718        var resourcePermissionDao = pm.ResourcePermissionDao;
719        var currentUserId = UserManager.CurrentUserId;
720        return pm.UseTransaction(() => {
721          var resourcePermissions = resourcePermissionDao.GetAll();
722          return slaveGroupDao.GetAll()
723            .Where(x => isAdministrator
724              || x.OwnerUserId == null
725              || x.OwnerUserId == currentUserId
726              || UserManager.VerifyUser(currentUserId, resourcePermissions
727                  .Where(y => y.ResourceId == x.ResourceId)
728                  .Select(z => z.GrantedUserId)
729                  .ToList())
730              )
731            .Select(x => x.ToDto())
732            .ToList();
733        });
734      }
735    }
736
737    public void UpdateSlave(DT.Slave slaveDto) {
738      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
739      var pm = PersistenceManager;
740      using (new PerformanceLogger("UpdateSlave")) {
741        var slaveDao = pm.SlaveDao;
742        pm.UseTransaction(() => {
743          var slave = slaveDao.GetById(slaveDto.Id);
744          if (slave != null) {
745            slaveDto.CopyToEntity(slave);
746          } else {
747            slaveDao.Save(slaveDto.ToEntity());
748          }
749          pm.SubmitChanges();
750        });
751      }
752    }
753
754    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
755      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
756      var pm = PersistenceManager;
757      using (new PerformanceLogger("UpdateSlaveGroup")) {
758        var slaveGroupDao = pm.SlaveGroupDao;
759        pm.UseTransaction(() => {
760          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
761          if (slaveGroup != null) {
762            slaveGroupDto.CopyToEntity(slaveGroup);
763          } else {
764            slaveGroupDao.Save(slaveGroupDto.ToEntity());
765          }
766          pm.SubmitChanges();
767        });
768      }
769    }
770
771    public void DeleteSlave(Guid slaveId) {
772      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
773      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
774      var pm = PersistenceManager;
775      using (new PerformanceLogger("DeleteSlave")) {
776        var slaveDao = pm.SlaveDao;
777        pm.UseTransaction(() => {
778          slaveDao.Delete(slaveId);
779        });
780      }
781    }
782
783    public void DeleteSlaveGroup(Guid slaveGroupId) {
784      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
785      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
786      var pm = PersistenceManager;
787      using (new PerformanceLogger("DeleteSlaveGroup")) {
788        var slaveGroupDao = pm.SlaveGroupDao;
789        pm.UseTransaction(() => {
790          slaveGroupDao.Delete(slaveGroupId);
791        });
792      }
793    }
794
795    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
796      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
797      var pm = PersistenceManager;
798      using (new PerformanceLogger("AddResourceToGroup")) {
799        var resourceDao = pm.ResourceDao;
800        pm.UseTransaction(() => {
801          var resource = resourceDao.GetById(resourceId);
802          resource.ParentResourceId = slaveGroupId;
803          pm.SubmitChanges();
804        });
805      }
806    }
807
808    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
809      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
810      var pm = PersistenceManager;
811      using (new PerformanceLogger("RemoveResourceFromGroup")) {
812        var resourceDao = pm.ResourceDao;
813        pm.UseTransaction(() => {
814          var resource = resourceDao.GetById(resourceId);
815          resource.ParentResourceId = null;
816          pm.SubmitChanges();
817        });
818      }
819    }
820
821    public Guid GetResourceId(string resourceName) {
822      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
823      var pm = PersistenceManager;
824      using (new PerformanceLogger("GetResourceId")) {
825        var resourceDao = pm.ResourceDao;
826        return pm.UseTransaction(() => {
827          var resource = resourceDao.GetByName(resourceName);
828          return resource != null ? resource.ResourceId : Guid.Empty;
829        });
830      }
831    }
832
833    public void TriggerEventManager(bool force) {
834      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
835      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
836      bool cleanup;
837      var pm = PersistenceManager;
838      using (new PerformanceLogger("TriggerEventManager")) {
839        cleanup = false;
840        var lifecycleDao = pm.LifecycleDao;
841        pm.UseTransaction(() => {
842          var lastLifecycle = lifecycleDao.GetLastLifecycle();
843          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
844          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
845            lifecycleDao.UpdateLifecycle();
846            cleanup = true;
847            pm.SubmitChanges();
848          }
849        }, true);
850      }
851      if (cleanup) {
852        EventManager.Cleanup();
853      }
854    }
855
856    public int GetNewHeartbeatInterval(Guid slaveId) {
857      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
858      var pm = PersistenceManager;
859      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
860        var slaveDao = pm.SlaveDao;
861        return pm.UseTransaction(() => {
862          var slave = slaveDao.GetById(slaveId);
863          if (slave != null) {
864            return slave.HbInterval;
865          }
866          return -1;
867        });
868      }
869    }
870    #endregion
871
872    #region Downtime Methods
873    public Guid AddDowntime(DT.Downtime downtimeDto) {
874      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
875      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
876      var pm = PersistenceManager;
877      using (new PerformanceLogger("AddDowntime")) {
878        var downtimeDao = pm.DowntimeDao;
879        return pm.UseTransaction(() => {
880          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
881          pm.SubmitChanges();
882          return downtime.ResourceId;
883        });
884      }
885    }
886
887    public void DeleteDowntime(Guid downtimeId) {
888      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
889      var pm = PersistenceManager;
890      using (new PerformanceLogger("DeleteDowntime")) {
891        var downtimeDao = pm.DowntimeDao;
892        pm.UseTransaction(() => {
893          downtimeDao.Delete(downtimeId);
894          pm.SubmitChanges();
895        });
896      }
897    }
898
899    public void UpdateDowntime(DT.Downtime downtimeDto) {
900      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
901      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
902      var pm = PersistenceManager;
903      using (new PerformanceLogger("UpdateDowntime")) {
904        var downtimeDao = pm.DowntimeDao;
905        pm.UseTransaction(() => {
906          var downtime = downtimeDao.GetById(downtimeDto.Id);
907          if (downtime != null) {
908            downtimeDto.CopyToEntity(downtime);
909          } else {
910            downtimeDao.Save(downtimeDto.ToEntity());
911          }
912          pm.SubmitChanges();
913        });
914      }
915    }
916
917    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
918      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
919      var pm = PersistenceManager;
920      using (new PerformanceLogger("GetDowntimesForResource")) {
921        var downtimeDao = pm.DowntimeDao;
922        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
923          .Select(x => x.ToDto())
924          .ToList()
925        );
926      }
927    }
928    #endregion
929
930    #region User Methods
931    public string GetUsernameByUserId(Guid userId) {
932      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
933      var user = UserManager.GetUserById(userId);
934      return user != null ? user.UserName : null;
935    }
936
937    public Guid GetUserIdByUsername(string username) {
938      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
939      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
940      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
941    }
942    #endregion
943
944    #region UserPriorities Methods
945    public IEnumerable<DT.UserPriority> GetUserPriorities() {
946      var pm = PersistenceManager;
947      using (new PerformanceLogger("GetUserPriorities")) {
948        var userPriorityDao = pm.UserPriorityDao;
949        return pm.UseTransaction(() => userPriorityDao.GetAll()
950          .Select(x => x.ToDto())
951          .ToList()
952        );
953      }
954    }
955    #endregion
956
957    #region Private Helper Methods
958    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
959      var stateLogDao = pm.StateLogDao;
960      var taskStateEntity = taskState.ToEntity();
961      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
962          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
963          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
964        task.Command = null;
965      } else if (taskStateEntity == DA.TaskState.Paused && task.Command != null) {
966        // slave paused and uploaded the task (no user-command) -> set waiting.
967        taskStateEntity = DA.TaskState.Waiting;
968      }
969      stateLogDao.Save(new DA.StateLog {
970        State = taskStateEntity,
971        DateTime = DateTime.Now,
972        TaskId = task.TaskId,
973        UserId = userId,
974        SlaveId = slaveId,
975        Exception = exception
976      });
977      task.State = taskStateEntity;
978    }
979
980    private DA.Resource AuthorizeForResource(IPersistenceManager pm, Guid resourceId) {
981      var resourceDao = pm.ResourceDao;
982      var resource = resourceDao.GetById(resourceId);
983      if (resource == null) throw new SecurityException("Not authorized");
984      if (resource.OwnerUserId != UserManager.CurrentUserId
985          && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
986        throw new SecurityException("Not authorized");
987      }
988      return resource;
989    }
990    #endregion
991  }
992}
Note: See TracBrowser for help on using the repository browser.