Skip to content

Commit

Permalink
add VmUsageLoggingSessions/report endpoint (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
sei-tspencer authored Aug 10, 2022
1 parent e2d3d05 commit f0195ef
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public async Task<FileResult> Handle(Query request, CancellationToken cancellati
var entry = _db.VmUsageLoggingSessions.FirstOrDefault(e => e.Id == request.SessionId);

if (entry == null)
throw new EntityNotFoundException<VmUsageLoggingSession>();
throw new EntityNotFoundException<VmUsageLoggingSession>();

if (!(await _playerService.IsSystemAdmin(cancellationToken) ||
await _playerService.IsViewAdmin(entry.ViewId, cancellationToken)))
Expand All @@ -88,22 +88,22 @@ await _playerService.IsViewAdmin(entry.ViewId, cancellationToken)))
}

string data = string.Join("\r\n", Array.ConvertAll(vmUsageLogEntries, s => {
return s.SessionId + ", " +
s.Id + ", " +
s.VmId + ", " +
s.VmName + ", " +
return s.SessionId + ", " +
s.Id + ", " +
s.VmId + ", " +
s.VmName + ", " +
s.IpAddress.Replace(", ", " ") + ", " +
s.UserId + ", " +
s.UserName + ", " +
s.VmActiveDT + ", " +
s.UserId + ", " +
s.UserName + ", " +
s.VmActiveDT + ", " +
s.VmInactiveDT;
}));

//Add header for CSV
data = "SessionID, LogID, VmID, VmName, IpAddress, UserId, UserName, VmActiveDateTime, VmInActiveDateTime\r\n" + data;
data = "SessionID, LogID, VmID, VmName, IpAddress, UserId, UserName, VmActiveDateTime, VmInactiveDateTime\r\n" + data;

byte[] bytes = Encoding.ASCII.GetBytes(data);

var result = new FileContentResult(bytes, "text/csv");
result.FileDownloadName = fileName;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
Crucible
Copyright 2022 Carnegie Mellon University.
NO WARRANTY. THIS CARNEGIE MELLON UNIVERSITY AND SOFTWARE ENGINEERING INSTITUTE MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
Released under a MIT (SEI)-style license, please see license.txt or contact [email protected] for full terms.
[DISTRIBUTION STATEMENT A] This material has been approved for public release and unlimited distribution. Please see Copyright notice for non-US Government use and distribution.
Carnegie Mellon(R) and CERT(R) are registered in the U.S. Patent and Trademark Office by Carnegie Mellon University.
DM20-0181
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Player.Vm.Api.Data;
using Player.Vm.Api.Domain.Services;
using Player.Vm.Api.Features.Vsphere;
using Player.Vm.Api.Infrastructure.Extensions;

namespace Player.Vm.Api.Features.VmUsageLoggingSession
{
public class GetVmUsageReport
{
[DataContract(Name="GetVmUsageReportQuery")]
public class Query : IRequest<List<VmUsageReport>>
{
/// <summary>
/// The Id of the VmUsageLoggingSession to retrieve log entries for
/// </summary>
[DataMember]
public DateTimeOffset ReportStart { get; set; }
public DateTimeOffset ReportEnd { get; set; }
}

public class Handler : IRequestHandler<Query, List<VmUsageReport>>
{
private readonly VmLoggingContext _db;
private readonly IMapper _mapper;
private readonly IAuthorizationService _authorizationService;
private readonly IPlayerService _playerService;
private readonly Guid _userId;

public Handler(
VmLoggingContext db,
IMapper mapper,
IAuthorizationService authorizationService,
IPrincipal principal,
IPlayerService playerService)
{
_db = db;
_mapper = mapper;
_authorizationService = authorizationService;
_userId = (principal as ClaimsPrincipal).GetId();
_playerService = playerService;
}

public async Task<List<VmUsageReport>> Handle(Query request, CancellationToken cancellationToken)
{
var sessionList = await _db.VmUsageLoggingSessions
.Where(s =>
request.ReportStart.CompareTo(s.SessionStart) <= 0 &&
request.ReportEnd.CompareTo(s.SessionEnd) >= 0)
.ToListAsync(cancellationToken);
var sessionIdList = sessionList.Select(s => s.Id);
List<VmUsageReport> vmUsageReportList;
var flatVmUsageLogEntryList = await _db.VmUsageLogEntries
.Where(e => sessionIdList.Contains(e.SessionId))
.Select(e => new {
SessionId = e.SessionId,
SessionName = e.Session.SessionName,
SessionStart = e.Session.SessionStart,
SessionEnd = e.Session.SessionEnd,
VmId = e.VmId,
VmName = e.VmName,
IpAddress = e.IpAddress,
UserId = e.UserId,
UserName = e.UserName,
VmActiveDT = e.VmActiveDT,
VmInactiveDT = e.VmInactiveDT
})
.ToListAsync();
// non-system admins can only get a report of their own activity
if (!await _playerService.IsSystemAdmin(cancellationToken))
{
flatVmUsageLogEntryList = flatVmUsageLogEntryList
.Where(f => f.UserId == _userId)
.ToList();
}
vmUsageReportList = flatVmUsageLogEntryList
.GroupBy(e => new {
e.SessionId,
e.VmId,
e.UserId})
.Select(g => new VmUsageReport {
SessionId = g.Key.SessionId,
SessionName = g.FirstOrDefault().SessionName,
SessionStart = g.FirstOrDefault().SessionStart,
SessionEnd = g.FirstOrDefault().SessionEnd,
VmId = g.Key.VmId,
VmName = g.FirstOrDefault().VmName,
IpAddress = g.FirstOrDefault().IpAddress,
UserId = g.Key.UserId,
UserName = g.FirstOrDefault().UserName,
MinutesActive = (int)g.Sum(x => x.VmInactiveDT.Subtract(x.VmActiveDT).TotalMinutes) })
.OrderBy(r => r.UserName)
.ThenBy(r => r.SessionName)
.ThenBy(r => r.VmName)
.ToList();

return vmUsageReportList;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class VmUsageLoggingSessionController : ControllerBase
{
private readonly IMediator _mediator;
private VmUsageLoggingOptions _options;

public VmUsageLoggingSessionController(IMediator mediator, IOptionsMonitor<VmUsageLoggingOptions> vsphereOptionsMonitor)
{
_mediator = mediator;
Expand Down Expand Up @@ -90,14 +90,14 @@ public async Task<IActionResult> GetAll(Guid? viewId, bool? onlyActive)
OnlyActive = onlyActive.HasValue ? onlyActive.Value : false,
ViewId = viewId.HasValue ? viewId.Value : null
});

return Ok(result);
}
else
{
return NotFound("Vm Usage Logging is disabled");
}
}
}

/// <summary>
/// Create a new VmUsageLoggingSession.
Expand Down Expand Up @@ -183,7 +183,7 @@ public async Task<IActionResult> EndSession([FromRoute] Guid id)
{
return NotFound("Vm Usage Logging is disabled");
}
}
}

/// <summary>
/// Get CSV file for all log entries in a VmUsageLoggingSession.
Expand All @@ -204,5 +204,27 @@ public async Task<IActionResult> GetVmUsageCsvFile([FromRoute] Guid id)
return NotFound("Vm Usage Logging is disabled");
}
}

/// <summary>
/// Get VM Usage Report for a timespan.
/// </summary>
/// <param name="reportStart">The start date/time for the report.</param>
/// <param name="reportEnd">IThe end date/time for the report.</param>
/// <returns></returns>
[HttpGet("report")]
[ProducesResponseType(typeof(List<VmUsageReport>), (int)HttpStatusCode.OK)]
[SwaggerOperation(OperationId = "GetVmUsageReport")]
public async Task<IActionResult> GetVmUsageReport([FromQuery] DateTimeOffset reportStart, DateTimeOffset reportEnd)
{
if (_options.Enabled)
{
var result = await _mediator.Send(new GetVmUsageReport.Query {ReportStart = reportStart, ReportEnd = reportEnd});
return Ok(result);
}
else
{
return NotFound("Vm Usage Logging is disabled");
}
}
}
}
32 changes: 32 additions & 0 deletions src/Player.Vm.Api/Features/VmUsageLoggingSession/VmUsageReport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Crucible
Copyright 2022 Carnegie Mellon University.
NO WARRANTY. THIS CARNEGIE MELLON UNIVERSITY AND SOFTWARE ENGINEERING INSTITUTE MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
Released under a MIT (SEI)-style license, please see license.txt or contact [email protected] for full terms.
[DISTRIBUTION STATEMENT A] This material has been approved for public release and unlimited distribution. Please see Copyright notice for non-US Government use and distribution.
Carnegie Mellon(R) and CERT(R) are registered in the U.S. Patent and Trademark Office by Carnegie Mellon University.
DM20-0181
*/

using System;
using System.Collections.Generic;

namespace Player.Vm.Api.Features.VmUsageLoggingSession
{
public class VmUsageReport
{
public Guid SessionId { get; set; }
public string SessionName { get; set; }
public DateTimeOffset SessionStart { get; set; }
public DateTimeOffset SessionEnd { get; set; }
public Guid VmId { get; set; }
public string VmName { get; set; }
public string IpAddress { get; set; }
public Guid UserId { get; set; }
public string UserName { get; set; }
public int MinutesActive { get; set; }

}


}

0 comments on commit f0195ef

Please sign in to comment.