source: stable/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 13166

Last change on this file since 13166 was 13166, checked in by ascheibe, 4 years ago

#2503 merged r13142 into stable

File size: 39.1 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          pm.SubmitChanges();
632        });
633      }
634    }
635
636    public IEnumerable<DT.ResourcePermission> GetResourcePermissions(Guid resourceId) {
637      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
638      var pm = PersistenceManager;
639      using (new PerformanceLogger("GetResourcePermissions")) {
640        var resourcePermissionDao = pm.ResourcePermissionDao;
641        return pm.UseTransaction(() => resourcePermissionDao.GetByResourceId(resourceId)
642          .Select(x => x.ToDto())
643          .ToList()
644        );
645      }
646    }
647    #endregion
648
649    #region Slave Methods
650    public Guid AddSlave(DT.Slave slaveDto) {
651      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
652      var pm = PersistenceManager;
653      using (new PerformanceLogger("AddSlave")) {
654        var slaveDao = pm.SlaveDao;
655        return pm.UseTransaction(() => {
656          var slave = slaveDao.Save(slaveDto.ToEntity());
657          pm.SubmitChanges();
658          return slave.ResourceId;
659        });
660      }
661    }
662
663    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
664      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
665      var pm = PersistenceManager;
666      using (new PerformanceLogger("AddSlaveGroup")) {
667        var slaveGroupDao = pm.SlaveGroupDao;
668        return pm.UseTransaction(() => {
669          if (slaveGroupDto.Id == Guid.Empty) {
670            slaveGroupDto.Id = Guid.NewGuid();
671          }
672          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
673          pm.SubmitChanges();
674          return slaveGroup.ResourceId;
675        });
676      }
677    }
678
679    public DT.Slave GetSlave(Guid slaveId) {
680      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
681      var pm = PersistenceManager;
682      using (new PerformanceLogger("GetSlave")) {
683        var slaveDao = pm.SlaveDao;
684        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
685      }
686    }
687
688    public IEnumerable<DT.Slave> GetSlaves() {
689      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
690      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
691      var pm = PersistenceManager;
692      using (new PerformanceLogger("GetSlaves")) {
693        var slaveDao = pm.SlaveDao;
694        var resourcePermissionDao = pm.ResourcePermissionDao;
695        var currentUserId = UserManager.CurrentUserId;
696        return pm.UseTransaction(() => {
697          var resourcePermissions = resourcePermissionDao.GetAll();
698          return slaveDao.GetAll().ToList()
699            .Where(x => isAdministrator
700              || x.OwnerUserId == null
701              || x.OwnerUserId == currentUserId
702              || UserManager.VerifyUser(currentUserId, resourcePermissions
703                  .Where(y => y.ResourceId == x.ResourceId)
704                  .Select(z => z.GrantedUserId)
705                  .ToList())
706              )
707            .Select(x => x.ToDto())
708            .ToList();
709        });
710      }
711    }
712
713    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
714      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
715      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
716      var pm = PersistenceManager;
717      using (new PerformanceLogger("GetSlaveGroups")) {
718        var slaveGroupDao = pm.SlaveGroupDao;
719        var resourcePermissionDao = pm.ResourcePermissionDao;
720        var currentUserId = UserManager.CurrentUserId;
721        return pm.UseTransaction(() => {
722          var resourcePermissions = resourcePermissionDao.GetAll();
723          return slaveGroupDao.GetAll().ToList()
724            .Where(x => isAdministrator
725              || x.OwnerUserId == null
726              || x.OwnerUserId == currentUserId
727              || UserManager.VerifyUser(currentUserId, resourcePermissions
728                  .Where(y => y.ResourceId == x.ResourceId)
729                  .Select(z => z.GrantedUserId)
730                  .ToList())
731              )
732            .Select(x => x.ToDto())
733            .ToList();
734        });
735      }
736    }
737
738    public void UpdateSlave(DT.Slave slaveDto) {
739      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
740      var pm = PersistenceManager;
741      using (new PerformanceLogger("UpdateSlave")) {
742        var slaveDao = pm.SlaveDao;
743        pm.UseTransaction(() => {
744          var slave = slaveDao.GetById(slaveDto.Id);
745          if (slave != null) {
746            slaveDto.CopyToEntity(slave);
747          } else {
748            slaveDao.Save(slaveDto.ToEntity());
749          }
750          pm.SubmitChanges();
751        });
752      }
753    }
754
755    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
756      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
757      var pm = PersistenceManager;
758      using (new PerformanceLogger("UpdateSlaveGroup")) {
759        var slaveGroupDao = pm.SlaveGroupDao;
760        pm.UseTransaction(() => {
761          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
762          if (slaveGroup != null) {
763            slaveGroupDto.CopyToEntity(slaveGroup);
764          } else {
765            slaveGroupDao.Save(slaveGroupDto.ToEntity());
766          }
767          pm.SubmitChanges();
768        });
769      }
770    }
771
772    public void DeleteSlave(Guid slaveId) {
773      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
774      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
775      var pm = PersistenceManager;
776      using (new PerformanceLogger("DeleteSlave")) {
777        var slaveDao = pm.SlaveDao;
778        pm.UseTransaction(() => {
779          slaveDao.Delete(slaveId);
780          pm.SubmitChanges();
781        });
782      }
783    }
784
785    public void DeleteSlaveGroup(Guid slaveGroupId) {
786      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
787      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
788      var pm = PersistenceManager;
789      using (new PerformanceLogger("DeleteSlaveGroup")) {
790        var slaveGroupDao = pm.SlaveGroupDao;
791        pm.UseTransaction(() => {
792          slaveGroupDao.Delete(slaveGroupId);
793          pm.SubmitChanges();
794        });
795      }
796    }
797
798    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
799      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
800      var pm = PersistenceManager;
801      using (new PerformanceLogger("AddResourceToGroup")) {
802        var resourceDao = pm.ResourceDao;
803        pm.UseTransaction(() => {
804          var resource = resourceDao.GetById(resourceId);
805          resource.ParentResourceId = slaveGroupId;
806          pm.SubmitChanges();
807        });
808      }
809    }
810
811    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
812      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
813      var pm = PersistenceManager;
814      using (new PerformanceLogger("RemoveResourceFromGroup")) {
815        var resourceDao = pm.ResourceDao;
816        pm.UseTransaction(() => {
817          var resource = resourceDao.GetById(resourceId);
818          resource.ParentResourceId = null;
819          pm.SubmitChanges();
820        });
821      }
822    }
823
824    public Guid GetResourceId(string resourceName) {
825      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
826      var pm = PersistenceManager;
827      using (new PerformanceLogger("GetResourceId")) {
828        var resourceDao = pm.ResourceDao;
829        return pm.UseTransaction(() => {
830          var resource = resourceDao.GetByName(resourceName);
831          return resource != null ? resource.ResourceId : Guid.Empty;
832        });
833      }
834    }
835
836    public void TriggerEventManager(bool force) {
837      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
838      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
839      bool cleanup;
840      var pm = PersistenceManager;
841      using (new PerformanceLogger("TriggerEventManager")) {
842        cleanup = false;
843        var lifecycleDao = pm.LifecycleDao;
844        pm.UseTransaction(() => {
845          var lastLifecycle = lifecycleDao.GetLastLifecycle();
846          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
847          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
848            lifecycleDao.UpdateLifecycle();
849            cleanup = true;
850            pm.SubmitChanges();
851          }
852        }, true);
853      }
854      if (cleanup) {
855        EventManager.Cleanup();
856      }
857    }
858
859    public int GetNewHeartbeatInterval(Guid slaveId) {
860      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
861      var pm = PersistenceManager;
862      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
863        var slaveDao = pm.SlaveDao;
864        return pm.UseTransaction(() => {
865          var slave = slaveDao.GetById(slaveId);
866          if (slave != null) {
867            return slave.HbInterval;
868          }
869          return -1;
870        });
871      }
872    }
873    #endregion
874
875    #region Downtime Methods
876    public Guid AddDowntime(DT.Downtime downtimeDto) {
877      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
878      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
879      var pm = PersistenceManager;
880      using (new PerformanceLogger("AddDowntime")) {
881        var downtimeDao = pm.DowntimeDao;
882        return pm.UseTransaction(() => {
883          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
884          pm.SubmitChanges();
885          return downtime.ResourceId;
886        });
887      }
888    }
889
890    public void DeleteDowntime(Guid downtimeId) {
891      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
892      var pm = PersistenceManager;
893      using (new PerformanceLogger("DeleteDowntime")) {
894        var downtimeDao = pm.DowntimeDao;
895        pm.UseTransaction(() => {
896          downtimeDao.Delete(downtimeId);
897          pm.SubmitChanges();
898        });
899      }
900    }
901
902    public void UpdateDowntime(DT.Downtime downtimeDto) {
903      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
904      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
905      var pm = PersistenceManager;
906      using (new PerformanceLogger("UpdateDowntime")) {
907        var downtimeDao = pm.DowntimeDao;
908        pm.UseTransaction(() => {
909          var downtime = downtimeDao.GetById(downtimeDto.Id);
910          if (downtime != null) {
911            downtimeDto.CopyToEntity(downtime);
912          } else {
913            downtimeDao.Save(downtimeDto.ToEntity());
914          }
915          pm.SubmitChanges();
916        });
917      }
918    }
919
920    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
921      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
922      var pm = PersistenceManager;
923      using (new PerformanceLogger("GetDowntimesForResource")) {
924        var downtimeDao = pm.DowntimeDao;
925        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
926          .Select(x => x.ToDto())
927          .ToList()
928        );
929      }
930    }
931    #endregion
932
933    #region User Methods
934    public string GetUsernameByUserId(Guid userId) {
935      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
936      var user = UserManager.GetUserById(userId);
937      return user != null ? user.UserName : null;
938    }
939
940    public Guid GetUserIdByUsername(string username) {
941      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
942      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
943      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
944    }
945    #endregion
946
947    #region UserPriorities Methods
948    public IEnumerable<DT.UserPriority> GetUserPriorities() {
949      var pm = PersistenceManager;
950      using (new PerformanceLogger("GetUserPriorities")) {
951        var userPriorityDao = pm.UserPriorityDao;
952        return pm.UseTransaction(() => userPriorityDao.GetAll()
953          .Select(x => x.ToDto())
954          .ToList()
955        );
956      }
957    }
958    #endregion
959
960    #region Private Helper Methods
961    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
962      var stateLogDao = pm.StateLogDao;
963      var taskStateEntity = taskState.ToEntity();
964      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
965          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
966          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
967        task.Command = null;
968      } else if (taskStateEntity == DA.TaskState.Paused && task.Command != null) {
969        // slave paused and uploaded the task (no user-command) -> set waiting.
970        taskStateEntity = DA.TaskState.Waiting;
971      }
972      stateLogDao.Save(new DA.StateLog {
973        State = taskStateEntity,
974        DateTime = DateTime.Now,
975        TaskId = task.TaskId,
976        UserId = userId,
977        SlaveId = slaveId,
978        Exception = exception
979      });
980      task.State = taskStateEntity;
981    }
982
983    private DA.Resource AuthorizeForResource(IPersistenceManager pm, Guid resourceId) {
984      var resourceDao = pm.ResourceDao;
985      var resource = resourceDao.GetById(resourceId);
986      if (resource == null) throw new SecurityException("Not authorized");
987      if (resource.OwnerUserId != UserManager.CurrentUserId
988          && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
989        throw new SecurityException("Not authorized");
990      }
991      return resource;
992    }
993    #endregion
994  }
995}
Note: See TracBrowser for help on using the repository browser.