source: branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 9469

Last change on this file since 9469 was 9469, checked in by pfleck, 6 years ago

#2030

Task- and Plugin-data is stored in the file system instead of the database.
This is accomplished by the Filestream feature of the SQL-Server.

Fixed bug when Heal-Group does not exist.

Note: SqlServer configuration changes are necessary for Filestream feature
http://www.codeproject.com/Articles/128657/How-Do-I-Use-SQL-File-Stream

File size: 31.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.ServiceModel;
26using HeuristicLab.Services.Hive.DataTransfer;
27using HeuristicLab.Services.Hive.ServiceContracts;
28using DA = HeuristicLab.Services.Hive.DataAccess;
29using DT = HeuristicLab.Services.Hive.DataTransfer;
30
31
32namespace HeuristicLab.Services.Hive {
33
34  /// <summary>
35  /// Implementation of the Hive service (interface <see cref="IHiveService"/>).
36  /// We need 'IgnoreExtensionDataObject' Attribute for the slave to work.
37  /// </summary>
38  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IgnoreExtensionDataObject = true)]
39  [HiveOperationContextBehavior]
40  public class HiveService : IHiveService {
41    private IHiveDao dao {
42      get { return ServiceLocator.Instance.HiveDao; }
43    }
44    private IOptimizedHiveDao optimizedDao {
45      get { return ServiceLocator.Instance.OptimizedHiveDao; }
46    }
47    private Access.IRoleVerifier authen {
48      get { return ServiceLocator.Instance.RoleVerifier; }
49    }
50    private IAuthorizationManager author {
51      get { return ServiceLocator.Instance.AuthorizationManager; }
52    }
53    private DataAccess.ITransactionManager trans {
54      get { return ServiceLocator.Instance.TransactionManager; }
55    }
56    private IEventManager eventManager {
57      get { return ServiceLocator.Instance.EventManager; }
58    }
59    private Access.IUserManager userManager {
60      get { return ServiceLocator.Instance.UserManager; }
61    }
62    private HeartbeatManager heartbeatManager {
63      get { return ServiceLocator.Instance.HeartbeatManager; }
64    }
65
66    #region Task Methods
67    public Guid AddTask(Task task, TaskData taskData, IEnumerable<Guid> resourceIds) {
68      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
69      return trans.UseTransaction(() => {
70        var t = DT.Convert.ToEntity(task);
71        t.RequiredPlugins.AddRange(task.PluginsNeededIds.Select(pluginId => new DA.RequiredPlugin { Task = t, PluginId = pluginId }));
72
73        t.JobData = DT.Convert.ToEntity(taskData);
74        t.JobData.LastUpdate = DateTime.Now;
75
76        optimizedDao.AddTask(t);
77
78        dao.AssignJobToResource(t.TaskId, resourceIds);
79
80        optimizedDao.UpdateTaskState(t.TaskId, DA.TaskState.Waiting, null, userManager.CurrentUserId, null);
81
82        return t.TaskId;
83      }, false, true);
84    }
85
86    public Guid AddChildTask(Guid parentTaskId, Task task, TaskData taskData) {
87      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
88      task.ParentTaskId = parentTaskId;
89      return AddTask(task, taskData, optimizedDao.GetAssignedResourceIds(parentTaskId));
90    }
91
92    public Task GetTask(Guid taskId) {
93      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
94      author.AuthorizeForTask(taskId, Permission.Read);
95
96      return trans.UseTransaction(() => {
97        return DT.Convert.ToDto(optimizedDao.GetTaskById(taskId));
98      }, false, false);
99    }
100
101    public IEnumerable<Task> GetTasks() {
102      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
103      return trans.UseTransaction(() => {
104        var tasks = dao.GetTasks(x => true);
105        foreach (var task in tasks)
106          author.AuthorizeForTask(task.Id, Permission.Read);
107        return tasks;
108      });
109    }
110
111    public IEnumerable<LightweightTask> GetLightweightTasks(IEnumerable<Guid> taskIds) {
112      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
113
114      return trans.UseTransaction(() => {
115        var tasks = dao.GetTasks(x => taskIds.Contains(x.TaskId)).Select(x => new LightweightTask(x)).ToArray();
116        foreach (var task in tasks)
117          author.AuthorizeForTask(task.Id, Permission.Read);
118        return tasks;
119      }, false, false);
120    }
121
122    public IEnumerable<LightweightTask> GetLightweightChildTasks(Guid? parentTaskId, bool recursive, bool includeParent) {
123      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
124
125      return trans.UseTransaction(() => {
126        var tasks = GetChildTasks(parentTaskId, recursive, includeParent).Select(x => new LightweightTask(x)).ToArray();
127        foreach (var task in tasks)
128          author.AuthorizeForTask(task.Id, Permission.Read);
129        return tasks;
130      }, false, false);
131    }
132
133    public IEnumerable<LightweightTask> GetLightweightJobTasks(Guid jobId) {
134      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
135      author.AuthorizeForJob(jobId, Permission.Read);
136
137      return trans.UseTransaction(() => {
138        return optimizedDao.GetLightweightTasks(jobId).ToArray();
139      }, false, true);
140    }
141
142    public IEnumerable<LightweightTask> GetLightweightJobTasksWithoutStateLog(Guid jobId) {
143      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
144      author.AuthorizeForJob(jobId, Permission.Read);
145
146      return trans.UseTransaction(() => {
147        return dao.GetLightweightTasksWithoutStateLog(task => task.JobId == jobId).ToArray();
148      }, false, false);
149    }
150
151    public TaskData GetTaskData(Guid taskId) {
152      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
153      author.AuthorizeForTask(taskId, Permission.Read);
154
155      return trans.UseTransaction(() => {
156        return dao.GetTaskData(taskId);
157      });
158    }
159
160    public void UpdateTask(Task taskDto) {
161      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
162      author.AuthorizeForTask(taskDto.Id, Permission.Full);
163
164      trans.UseTransaction(() => {
165        var task = optimizedDao.GetTaskByDto(taskDto);
166        optimizedDao.UpdateTask(task);
167      });
168    }
169
170    public void UpdateTaskData(Task task, TaskData taskData) {
171      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
172      author.AuthorizeForTask(task.Id, Permission.Full);
173
174      trans.UseTransaction(() => {
175        var t = optimizedDao.GetTaskByDto(task);
176        optimizedDao.UpdateTask(t);
177      });
178
179      trans.UseTransaction(() => {
180        var data = optimizedDao.GetTaskDataByDto(taskData);
181        data.LastUpdate = DateTime.Now;
182        optimizedDao.UpdateTaskData(data);
183      });
184    }
185
186    public void DeleteTask(Guid taskId) {
187      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
188      author.AuthorizeForTask(taskId, Permission.Full);
189      trans.UseTransaction(() => {
190        dao.DeleteTask(taskId);
191      });
192    }
193
194    public void DeleteChildTasks(Guid parentTaskId) {
195      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
196      author.AuthorizeForTask(parentTaskId, Permission.Full);
197      trans.UseTransaction(() => {
198        var tasks = GetChildTasks(parentTaskId, true, false);
199        foreach (var task in tasks) {
200          dao.DeleteTask(task.Id);
201          dao.DeleteTaskData(task.Id);
202        };
203      });
204    }
205
206    public Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
207      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
208      author.AuthorizeForTask(taskId, Permission.Full);
209
210      return trans.UseTransaction(() => {
211        var task = optimizedDao.UpdateTaskState(taskId, DT.Convert.ToEntity(taskState), slaveId, userId, exception);
212
213        if (task.Command.HasValue && task.Command.Value == DA.Command.Pause && task.State == DA.TaskState.Paused) {
214          task.Command = null;
215        } else if (task.Command.HasValue && task.Command.Value == DA.Command.Abort && task.State == DA.TaskState.Aborted) {
216          task.Command = null;
217        } else if (task.Command.HasValue && task.Command.Value == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
218          task.Command = null;
219        } else if (taskState == TaskState.Paused && !task.Command.HasValue) {
220          // slave paused and uploaded the task (no user-command) -> set waiting.
221          task = optimizedDao.UpdateTaskState(taskId, DA.TaskState.Waiting, slaveId, userId, exception);
222        }
223
224        //optimizedDao.UpdateTaskAndPlugins(task); no idea why this is needed
225        return DT.Convert.ToDto(task);
226      });
227    }
228
229    public IEnumerable<Task> GetTasksByResourceId(Guid resourceId) {
230      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
231      var tasks = trans.UseTransaction(() => dao.GetJobsByResourceId(resourceId));
232      foreach (var task in tasks)
233        author.AuthorizeForTask(task.Id, Permission.Read);
234      return tasks;
235    }
236    #endregion
237
238    #region Task Control Methods
239    public void StopTask(Guid taskId) {
240      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
241      author.AuthorizeForTask(taskId, Permission.Full);
242      trans.UseTransaction(() => {
243        var task = dao.GetTask(taskId);
244        if (task.State == TaskState.Calculating || task.State == TaskState.Transferring) {
245          task.Command = Command.Stop;
246          dao.UpdateTask(task);
247        } else {
248          if (task.State != TaskState.Aborted && task.State != TaskState.Finished && task.State != TaskState.Failed) {
249            task = UpdateTaskState(taskId, TaskState.Aborted, null, null, string.Empty);
250          }
251        }
252      });
253    }
254
255    public void PauseTask(Guid taskId) {
256      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
257      author.AuthorizeForTask(taskId, Permission.Full);
258      trans.UseTransaction(() => {
259        var job = dao.GetTask(taskId);
260        if (job.State == TaskState.Calculating || job.State == TaskState.Transferring) {
261          job.Command = Command.Pause;
262          dao.UpdateTask(job);
263        } else {
264          job = UpdateTaskState(taskId, TaskState.Paused, null, null, string.Empty);
265        }
266      });
267    }
268
269    public void RestartTask(Guid taskId) {
270      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
271      author.AuthorizeForTask(taskId, Permission.Full);
272      trans.UseTransaction(() => {
273        Task task = dao.UpdateTaskState(taskId, DA.TaskState.Waiting, null, userManager.CurrentUserId, string.Empty);
274        task.Command = null;
275        dao.UpdateTask(task);
276      });
277    }
278    #endregion
279
280    #region Job Methods
281    public Job GetJob(Guid id) {
282      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
283      author.AuthorizeForJob(id, Permission.Read);
284      return trans.UseTransaction(() => {
285        var job = dao.GetJobs(x =>
286              x.JobId == id
287              && (x.OwnerUserId == userManager.CurrentUserId || x.JobPermissions.Count(hep => hep.Permission != DA.Permission.NotAllowed && hep.GrantedUserId == userManager.CurrentUserId) > 0)
288            ).FirstOrDefault();
289        if (job != null) {
290          job.Permission = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
291          job.OwnerUsername = userManager.GetUserById(job.OwnerUserId).UserName;
292        }
293        return job;
294      });
295    }
296
297    public IEnumerable<Job> GetJobs() {
298      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
299      return trans.UseTransaction(() => {
300        var jobs = dao.GetJobs(x => x.OwnerUserId == userManager.CurrentUserId || x.JobPermissions.Count(hep => hep.Permission != DA.Permission.NotAllowed && hep.GrantedUserId == userManager.CurrentUserId) > 0);
301        foreach (var job in jobs) {
302          author.AuthorizeForJob(job.Id, Permission.Read);
303          job.Permission = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
304          job.OwnerUsername = userManager.GetUserById(job.OwnerUserId).UserName;
305        }
306        return jobs;
307      });
308    }
309
310    public IEnumerable<Job> GetAllJobs() {
311      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
312      return trans.UseTransaction(() => {
313        var jobs = dao.GetJobs(x => true);
314        foreach (var job in jobs) { // no authorization here, since this method is admin-only! (admin is allowed to read all task)
315          job.Permission = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
316          job.OwnerUsername = userManager.GetUserById(job.OwnerUserId).UserName;
317        }
318        return jobs;
319      });
320    }
321
322    public Guid AddJob(Job jobDto) {
323      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
324      return trans.UseTransaction(() => {
325        jobDto.OwnerUserId = userManager.CurrentUserId;
326        jobDto.DateCreated = DateTime.Now;
327        return dao.AddJob(jobDto);
328      });
329    }
330
331    public void UpdateJob(Job jobDto) {
332      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
333      author.AuthorizeForJob(jobDto.Id, Permission.Full);
334      trans.UseTransaction(() => {
335        dao.UpdateJob(jobDto);
336      });
337    }
338
339    public void DeleteJob(Guid jobId) {
340      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
341      author.AuthorizeForJob(jobId, Permission.Full);
342      trans.UseTransaction(() => {
343        dao.DeleteJob(jobId); // child task will be deleted by db-trigger
344      });
345    }
346    #endregion
347
348    #region JobPermission Methods
349    public void GrantPermission(Guid jobId, Guid grantedUserId, Permission permission) {
350      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
351      trans.UseTransaction(() => {
352        Job job = dao.GetJob(jobId);
353        if (job == null) throw new FaultException<FaultReason>(new FaultReason("Could not find task with id " + jobId));
354        Permission perm = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
355        if (perm != Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permissions for this experiment"));
356        dao.SetJobPermission(jobId, userManager.CurrentUserId, grantedUserId, DT.Convert.ToEntity(permission));
357      });
358    }
359
360    public void RevokePermission(Guid jobId, Guid grantedUserId) {
361      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
362      trans.UseTransaction(() => {
363        Job job = dao.GetJob(jobId);
364        if (job == null) throw new FaultException<FaultReason>(new FaultReason("Could not find task with id " + jobId));
365        DA.Permission perm = dao.GetPermissionForJob(job.Id, userManager.CurrentUserId);
366        if (perm != DA.Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permissions for this experiment"));
367        dao.SetJobPermission(jobId, userManager.CurrentUserId, grantedUserId, DA.Permission.NotAllowed);
368      });
369    }
370
371    public IEnumerable<JobPermission> GetJobPermissions(Guid jobId) {
372      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
373      return trans.UseTransaction(() => {
374        DA.Permission currentUserPermission = dao.GetPermissionForJob(jobId, userManager.CurrentUserId);
375        if (currentUserPermission != DA.Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to list permissions for this experiment"));
376        return dao.GetJobPermissions(x => x.JobId == jobId);
377      });
378    }
379
380    public bool IsAllowedPrivileged() {
381      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
382      return authen.IsInRole(HiveRoles.IsAllowedPrivileged);
383    }
384    #endregion
385
386    #region Login Methods
387    public void Hello(Slave slaveInfo) {
388      authen.AuthenticateForAnyRole(HiveRoles.Slave);
389      if (userManager.CurrentUser.UserName != "hiveslave")
390        slaveInfo.OwnerUserId = userManager.CurrentUserId;
391
392      trans.UseTransaction(() => {
393        var slave = dao.GetSlave(slaveInfo.Id);
394
395        if (slave == null) {
396          var healGroup = dao.GetResources(x => x.Name == "HEAL").FirstOrDefault();
397          if (healGroup != null) {
398            slaveInfo.ParentResourceId = healGroup.Id;
399          }
400          dao.AddSlave(slaveInfo);
401        } else {
402          slave.Name = slaveInfo.Name;
403          slave.Description = slaveInfo.Description;
404          slave.OwnerUserId = slaveInfo.OwnerUserId;
405
406          slave.Cores = slaveInfo.Cores;
407          slave.CpuArchitecture = slaveInfo.CpuArchitecture;
408          slave.CpuSpeed = slaveInfo.CpuSpeed;
409          slave.FreeCores = slaveInfo.FreeCores;
410          slave.FreeMemory = slaveInfo.FreeMemory;
411          slave.Memory = slaveInfo.Memory;
412          slave.OperatingSystem = slaveInfo.OperatingSystem;
413
414          slave.LastHeartbeat = DateTime.Now;
415          slave.SlaveState = SlaveState.Idle;
416
417          // don't update those properties: dbSlave.IsAllowedToCalculate, dbSlave.ParentResourceId
418
419          dao.UpdateSlave(slave);
420        }
421      });
422    }
423
424    public void GoodBye(Guid slaveId) {
425      authen.AuthenticateForAnyRole(HiveRoles.Slave);
426      trans.UseTransaction(() => {
427        var slave = dao.GetSlave(slaveId);
428        if (slave != null) {
429          slave.SlaveState = SlaveState.Offline;
430          dao.UpdateSlave(slave);
431        }
432      });
433    }
434    #endregion
435
436    #region Heartbeat Methods
437    public List<MessageContainer> Heartbeat(Heartbeat heartbeat) {
438      authen.AuthenticateForAnyRole(HiveRoles.Slave);
439
440      List<MessageContainer> result = new List<MessageContainer>();
441      try {
442        result = heartbeatManager.ProcessHeartbeat(heartbeat);
443      }
444      catch (Exception ex) {
445        DA.LogFactory.GetLogger(this.GetType().Namespace).Log("Exception processing Heartbeat: " + ex.ToString());
446      }
447
448      if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
449        TriggerEventManager(false);
450      }
451
452      return result;
453    }
454    #endregion
455
456    #region Plugin Methods
457    public Guid AddPlugin(Plugin plugin, List<PluginData> pluginDatas) {
458      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
459      return trans.UseTransaction(() => {
460        plugin.UserId = userManager.CurrentUserId;
461        plugin.DateCreated = DateTime.Now;
462
463        var existing = dao.GetPlugins(x => x.Hash != null).Where(x => x.Hash.SequenceEqual(plugin.Hash));
464        if (existing.Count() > 0) {
465          // a plugin already exists.
466          throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(existing.Single().Id));
467        }
468
469        Guid pluginId = dao.AddPlugin(plugin);
470        foreach (PluginData pluginData in pluginDatas) {
471          pluginData.PluginId = pluginId;
472          dao.AddPluginData(pluginData);
473        }
474        return pluginId;
475      });
476    }
477
478    public Plugin GetPlugin(Guid pluginId) {
479      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
480      return trans.UseTransaction(() => {
481        return DT.Convert.ToDto(optimizedDao.GetPluginById(pluginId));
482      });
483    }
484
485    public Plugin GetPluginByHash(byte[] hash) {
486      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
487      return trans.UseTransaction(() => {
488        return dao.GetPlugins(x => x.Hash == hash).FirstOrDefault();
489      });
490    }
491
492    // note: this is a possible security problem, since a client is able to download all plugins, which may contain proprietary code (which can be disassembled)
493    //       change so that only with GetPluginByHash it is possible to download plugins
494    public IEnumerable<Plugin> GetPlugins() {
495      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
496      return trans.UseTransaction(() => {
497        return dao.GetPlugins(x => x.Hash != null);
498      });
499    }
500
501    public IEnumerable<PluginData> GetPluginDatas(List<Guid> pluginIds) {
502      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
503      var pluginDatas = new List<PluginData>();
504      return trans.UseTransaction(() => {
505        foreach (Guid guid in pluginIds) {
506          pluginDatas.AddRange(dao.GetPluginDatas(x => x.PluginId == guid).ToList());
507        }
508        return pluginDatas;
509      });
510    }
511
512    public void DeletePlugin(Guid pluginId) {
513      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
514      trans.UseTransaction(() => {
515        dao.DeletePlugin(pluginId);
516      });
517    }
518    #endregion
519
520    #region ResourcePermission Methods
521    public void GrantResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
522      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
523      trans.UseTransaction(() => {
524        Resource resource = dao.GetResource(resourceId);
525        if (resource == null) throw new FaultException<FaultReason>(new FaultReason("Could not find resource with id " + resourceId));
526        if (resource.OwnerUserId != userManager.CurrentUserId && !authen.IsInRole(HiveRoles.Administrator)) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permission for this resource"));
527        foreach (Guid id in grantedUserIds)
528          dao.AddResourcePermission(new ResourcePermission { ResourceId = resourceId, GrantedByUserId = userManager.CurrentUserId, GrantedUserId = id });
529      });
530    }
531
532    public void RevokeResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
533      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
534      trans.UseTransaction(() => {
535        Resource resource = dao.GetResource(resourceId);
536        if (resource == null) throw new FaultException<FaultReason>(new FaultReason("Could not find resource with id " + resourceId));
537        if (resource.OwnerUserId != userManager.CurrentUserId && !authen.IsInRole(HiveRoles.Administrator)) throw new FaultException<FaultReason>(new FaultReason("Not allowed to revoke permission for this resource"));
538        foreach (Guid id in grantedUserIds)
539          dao.DeleteResourcePermission(resourceId, id);
540      });
541    }
542
543    public IEnumerable<ResourcePermission> GetResourcePermissions(Guid resourceId) {
544      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
545      return trans.UseTransaction(() => {
546        Resource resource = dao.GetResource(resourceId);
547        if (resource == null) throw new FaultException<FaultReason>(new FaultReason("Could not find resource with id " + resourceId));
548        return dao.GetResourcePermissions(x => x.ResourceId == resourceId);
549      });
550    }
551    #endregion
552
553    #region Resource Methods
554    public IEnumerable<Resource> GetChildResources(Guid resourceId) {
555      return trans.UseTransaction(() => { return dao.GetChildResources(resourceId); });
556    }
557    #endregion
558
559    #region Slave Methods
560    public int GetNewHeartbeatInterval(Guid slaveId) {
561      authen.AuthenticateForAnyRole(HiveRoles.Slave);
562
563      Slave s = trans.UseTransaction(() => { return dao.GetSlave(slaveId); });
564      if (s != null) {
565        return s.HbInterval;
566      } else {
567        return -1;
568      }
569    }
570
571    public Guid AddSlave(Slave slave) {
572      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
573      return trans.UseTransaction(() => dao.AddSlave(slave));
574    }
575
576    public Guid AddSlaveGroup(SlaveGroup slaveGroup) {
577      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
578      return trans.UseTransaction(() => dao.AddSlaveGroup(slaveGroup));
579    }
580
581    public Slave GetSlave(Guid slaveId) {
582      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
583      return trans.UseTransaction(() => { return dao.GetSlave(slaveId); });
584    }
585
586    public SlaveGroup GetSlaveGroup(Guid slaveGroupId) {
587      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
588      return trans.UseTransaction(() => { return dao.GetSlaveGroup(slaveGroupId); });
589    }
590
591    public IEnumerable<Slave> GetSlaves() {
592      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
593      return trans.UseTransaction(() => {
594        return dao.GetSlaves(x => true).Where(x => x.OwnerUserId == null
595                                           || x.OwnerUserId == userManager.CurrentUserId
596                                           || userManager.VerifyUser(userManager.CurrentUserId, GetResourcePermissions(x.Id).Select(y => y.GrantedUserId).ToList())
597                                           || authen.IsInRole(HiveRoles.Administrator)).ToArray();
598      });
599    }
600
601    public IEnumerable<SlaveGroup> GetSlaveGroups() {
602      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
603      return trans.UseTransaction(() => {
604        return dao.GetSlaveGroups(x => true).Where(x => x.OwnerUserId == null
605                                                || x.OwnerUserId == userManager.CurrentUserId
606                                                || userManager.VerifyUser(userManager.CurrentUserId, GetResourcePermissions(x.Id).Select(y => y.GrantedUserId).ToList())
607                                                || authen.IsInRole(HiveRoles.Administrator)).ToArray();
608      });
609    }
610
611    public void UpdateSlave(Slave slave) {
612      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
613      trans.UseTransaction(() => {
614        dao.UpdateSlave(slave);
615      });
616    }
617
618    public void UpdateSlaveGroup(SlaveGroup slaveGroup) {
619      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
620      trans.UseTransaction(() => {
621        dao.UpdateSlaveGroup(slaveGroup);
622      });
623    }
624
625    public void DeleteSlave(Guid slaveId) {
626      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
627      author.AuthorizeForResourceAdministration(slaveId);
628      trans.UseTransaction(() => {
629        dao.DeleteSlave(slaveId);
630      });
631    }
632
633    public void DeleteSlaveGroup(Guid slaveGroupId) {
634      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
635      author.AuthorizeForResourceAdministration(slaveGroupId);
636      trans.UseTransaction(() => {
637        dao.DeleteSlaveGroup(slaveGroupId);
638      });
639    }
640
641    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
642      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
643      trans.UseTransaction(() => {
644        var resource = dao.GetResource(resourceId);
645        resource.ParentResourceId = slaveGroupId;
646        dao.UpdateResource(resource);
647      });
648    }
649
650    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
651      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
652      trans.UseTransaction(() => {
653        var resource = dao.GetResource(resourceId);
654        resource.ParentResourceId = null;
655        dao.UpdateResource(resource);
656      });
657    }
658
659    public Guid GetResourceId(string resourceName) {
660      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
661      return trans.UseTransaction(() => {
662        var resource = dao.GetResources(x => x.Name == resourceName).FirstOrDefault();
663        if (resource != null) {
664          return resource.Id;
665        } else {
666          return Guid.Empty;
667        }
668      });
669    }
670
671    public void TriggerEventManager(bool force) {
672      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Slave);
673      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
674      bool cleanup = false;
675      trans.UseTransaction(() => {
676        DateTime lastCleanup = dao.GetLastCleanup();
677        if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
678          dao.SetLastCleanup(DateTime.Now);
679          cleanup = true;
680        }
681      }, true);
682
683      if (cleanup) {
684        eventManager.Cleanup();
685      }
686    }
687    #endregion
688
689    #region Downtime Methods
690    public Guid AddDowntime(Downtime downtime) {
691      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
692      author.AuthorizeForResourceAdministration(downtime.ResourceId);
693      return trans.UseTransaction(() => dao.AddDowntime(downtime));
694    }
695
696    public void DeleteDowntime(Guid downtimeId) {
697      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
698      // TODO: pass resource id
699      // author.AuthorizeForResource(resourceId);
700      trans.UseTransaction(() => {
701        dao.DeleteDowntime(downtimeId);
702      });
703    }
704
705    public void UpdateDowntime(Downtime downtime) {
706      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
707      author.AuthorizeForResourceAdministration(downtime.ResourceId);
708      trans.UseTransaction(() => {
709        dao.UpdateDowntime(downtime);
710      });
711    }
712
713    public IEnumerable<Downtime> GetDowntimesForResource(Guid resourceId) {
714      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
715      return trans.UseTransaction(() => dao.GetDowntimes(x => x.ResourceId == resourceId));
716    }
717    #endregion
718
719    #region User Methods
720    public string GetUsernameByUserId(Guid userId) {
721      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
722      var user = ServiceLocator.Instance.UserManager.GetUserById(userId);
723      if (user != null)
724        return user.UserName;
725      else
726        return null;
727    }
728
729    public Guid GetUserIdByUsername(string username) {
730      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
731      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
732      return user != null ? (Guid)user.ProviderUserKey : Guid.Empty;
733    }
734    #endregion
735
736    #region UserPriority Methods
737    public IEnumerable<UserPriority> GetUserPriorities() {
738      return trans.UseTransaction(() => dao.GetUserPriorities(x => true));
739    }
740    #endregion
741
742    #region Helper Methods
743    private IEnumerable<Task> GetChildTasks(Guid? parentTaskId, bool recursive, bool includeParent) {
744      var tasks = new List<Task>(dao.GetTasks(x => parentTaskId == null ? !x.ParentTaskId.HasValue : x.ParentTaskId.Value == parentTaskId));
745
746      if (recursive) {
747        var childs = new List<Task>();
748        foreach (var task in tasks) {
749          childs.AddRange(GetChildTasks(task.Id, recursive, false));
750        }
751        tasks.AddRange(childs);
752      }
753
754      if (includeParent) tasks.Add(GetTask(parentTaskId.Value));
755      return tasks;
756    }
757    #endregion
758
759    #region Statistics Methods
760    public IEnumerable<Statistics> GetStatistics() {
761      return trans.UseTransaction(() => { return dao.GetStatistics(x => true); });
762    }
763    public IEnumerable<Statistics> GetStatisticsForTimePeriod(DateTime from, DateTime to) {
764      return trans.UseTransaction(() => { return dao.GetStatistics(x => x.Timestamp >= from && x.Timestamp <= to); });
765    }
766    #endregion
767  }
768}
Note: See TracBrowser for help on using the repository browser.