private async Task Deploy(Data.Gamespace gamespace) { var tasks = new List <Task <Vm> >(); var spec = JsonSerializer.Deserialize <ChallengeSpec>(gamespace.Challenge ?? "{}", jsonOptions); var templates = Mapper.Map <List <ConvergedTemplate> >(gamespace.Workspace.Templates); foreach (var template in templates) { // apply template macro substitutions foreach (string key in spec.Randoms.Keys) { template.Guestinfo = template.Guestinfo?.Replace(key, spec.Randoms[key]); template.Detail = template.Detail?.Replace(key, spec.Randoms[key]); } // TODO: add template replicas tasks.Add( _pod.Deploy( template.ToVirtualTemplate(gamespace.GlobalId) ) ); } await Task.WhenAll(tasks.ToArray()); }
public async Task <GameState> Launch(GamespaceSpec spec) { var game = await _gamespaceStore.Load(spec.IsolationId); if (game == null) { var workspace = await _workspaceStore.Load(spec.WorkspaceId); if (workspace == null || !workspace.HasScope(Client.Scope)) { _logger.LogInformation($"No audience match for workspace {spec?.WorkspaceId}: [{workspace?.Audience}] [{Client?.Scope}]"); throw new InvalidOperationException(); } game = new Data.Gamespace { GlobalId = spec.IsolationId, Name = workspace.Name, Workspace = workspace, Audience = Client.Id.Untagged() // ShareCode = Guid.NewGuid().ToString("N") }; await _gamespaceStore.Add(game); } return(await Deploy(await _gamespaceStore.Load(game.Id), spec)); }
private async Task <GameState> Destroy(Data.Gamespace gamespace) { if (gamespace == null || !gamespace.CanEdit(User)) { return(null); } await _pod.DeleteAll(gamespace.GlobalId); await _gamespaceStore.Delete(gamespace.Id); return(Mapper.Map <GameState>(gamespace)); }
private async Task <GameState> LoadState(Data.Gamespace gamespace) { var state = Mapper.Map <GameState>(gamespace); state.Vms = gamespace.Workspace.Templates .Where(t => !t.IsHidden) .Select(t => new VmState { Name = t.Name, TemplateId = t.Id }) .ToArray(); state.MergeVms(await _pod.Find(gamespace.GlobalId)); return(state); }
public async Task <GameState> Launch(int workspaceId) { var gamespaces = await _gamespaceStore .ListByProfile(User.Id) .ToArrayAsync(); var game = gamespaces .Where(m => m.WorkspaceId == workspaceId) .SingleOrDefault(); if (game == null) { var workspace = await _workspaceStore.Load(workspaceId); if (workspace == null) { throw new InvalidOperationException(); } if (gamespaces.Length >= _options.GamespaceLimit) { throw new GamespaceLimitReachedException(); } game = new Data.Gamespace { Name = workspace.Name, Workspace = workspace, LastActivity = DateTime.UtcNow, ShareCode = Guid.NewGuid().ToString("N"), Audience = "topomojo" }; game.Players.Add( new Data.Player { PersonId = User.Id, Permission = Data.Permission.Manager // LastSeen = DateTime.UtcNow } ); await _gamespaceStore.Add(game); } return(await Deploy(await _gamespaceStore.Load(game.Id))); }
private async Task <GameState> Deploy(Data.Gamespace gamespace, GamespaceSpec spec) { var deployTasks = new List <Task <Vm> >(); try { var templates = String.IsNullOrEmpty(spec.Templates) ? Mapper.Map <List <ConvergedTemplate> >(gamespace.Workspace.Templates) : JsonSerializer.Deserialize <List <ConvergedTemplate> >(spec.Templates); ApplyIso(templates, spec); ExpandTemplates(templates, spec); // await AddNetworkServer(templates, spec); foreach (var template in templates) { var virtualTemplate = template.ToVirtualTemplate(gamespace.GlobalId); if (spec.HostAffinity) { virtualTemplate.AutoStart = false; } deployTasks.Add(_pod.Deploy(virtualTemplate)); } Task.WaitAll(deployTasks.ToArray()); if (spec.HostAffinity) { await _pod.SetAffinity(gamespace.GlobalId, deployTasks.Select(t => t.Result).ToArray(), true); } } catch (Exception ex) { _logger.LogError(ex, "Error deploying Engine mojo"); throw ex; } return(await LoadState(gamespace, gamespace.WorkspaceId)); }
private async Task <GameState> Deploy(Data.Gamespace gamespace) { var tasks = new List <Task <Vm> >(); var templates = Mapper.Map <List <ConvergedTemplate> >(gamespace.Workspace.Templates); foreach (var template in templates) { tasks.Add( _pod.Deploy( template.ToVirtualTemplate(gamespace.GlobalId) ) ); } Task.WaitAll(tasks.ToArray()); return(await LoadState(gamespace, gamespace.WorkspaceId)); }
private async Task <GameState> LoadState(Data.Gamespace gamespace, int workspaceId) { GameState state = null; if (gamespace == null) { var workspace = await _workspaceStore.Load(workspaceId); if (workspace == null || !workspace.IsPublished) { throw new InvalidOperationException(); } state = new GameState(); state.Name = gamespace?.Name ?? workspace.Name; state.WorkspaceDocument = workspace.Document; state.Vms = workspace.Templates .Where(t => !t.IsHidden) .Select(t => new VmState { Name = t.Name, TemplateId = t.Id }) .ToArray(); } else { state = Mapper.Map <GameState>(gamespace); state.Vms = gamespace.Workspace.Templates .Where(t => !t.IsHidden) .Select(t => new VmState { Name = t.Name, TemplateId = t.Id }) .ToArray(); state.MergeVms(await _pod.Find(gamespace.GlobalId)); } return(state); }
private async Task <Data.Gamespace> Create( Data.Workspace workspace, string client, string isolationId ) { var gamespace = new Data.Gamespace { GlobalId = isolationId, Name = workspace.Name, Workspace = workspace, ShareCode = Guid.NewGuid().ToString("n"), Audience = client }; gamespace.Players.Add( new Data.Player { PersonId = User.Id, Permission = Data.Permission.Manager // LastSeen = DateTime.UtcNow } ); // glean randomize targets var regex = new Regex("##[^#]*##"); var map = new Dictionary <string, string>(); foreach (var t in gamespace.Workspace.Templates) { foreach (Match match in regex.Matches(t.Guestinfo ?? "")) { map.TryAdd(match.Value, ""); } foreach (Match match in regex.Matches(t.Detail ?? t.Parent?.Detail ?? "")) { map.TryAdd(match.Value, ""); } } // clone challenge var spec = new ChallengeSpec(); if (!string.IsNullOrEmpty(workspace.Challenge)) { spec = JsonSerializer.Deserialize <ChallengeSpec>(workspace.Challenge ?? "{}", jsonOptions); foreach (var question in spec.Questions) { foreach (Match match in regex.Matches(question.Answer)) { string key = match.Value; string val = ""; if (key.Contains(":list##")) { string[] list = question.Answer .Split(' ', StringSplitOptions.RemoveEmptyEntries) .Skip(1) .ToArray(); if (list.Length > 0) { val = list[_random.Next(list.Length)]; question.Answer = key; if (map.ContainsKey(key)) { map[key] = val; } } } map.TryAdd(key, val); } } } // resolve macros foreach (string key in map.Keys.ToArray()) { if (string.IsNullOrEmpty(map[key])) { map[key] = ResolveRandom(key); } } // apply macros to spec answers foreach (var q in spec.Questions) { foreach (string key in map.Keys) { q.Answer = q.Answer.Replace(key, map[key]); } } spec.Randoms = map; gamespace.Challenge = JsonSerializer.Serialize(spec, jsonOptions); await _gamespaceStore.Add(gamespace); return(gamespace); }
private async Task <GameState> LoadState(Data.Gamespace gamespace, int topoId) { GameState state = null; // gamespace should never be null in the engine service if (gamespace == null) { Data.Workspace topo = await _workspaceStore.Load(topoId); if (topo == null || !topo.IsPublished) { throw new InvalidOperationException(); } state = new GameState(); state.Name = gamespace?.Name ?? topo.Name; state.WorkspaceDocument = topo.Document; state.Vms = topo.Templates .Where(t => !t.IsHidden) .Select(t => new VmState { Name = t.Name, TemplateId = t.Id }) .ToArray(); } else { // get vm's, look up template, add if template not mark as hidden. state = Mapper.Map <GameState>(gamespace); var vmState = new List <VmState>(); var vms = await _pod.Find(gamespace.GlobalId); foreach (Vm vm in vms) { string name = vm.Name.Untagged(); // a vm could be a replica, denoted by `_1` or some number, // so strip that to find template. int x = name.LastIndexOf('_'); var tmpl = gamespace.Workspace.Templates .Where(t => !t.IsHidden && t.Name == name) .FirstOrDefault(); if (tmpl == null && x == name.Length - 2) { name = name.Substring(0, x); tmpl = gamespace.Workspace.Templates .Where(t => !t.IsHidden && t.Name == name) .FirstOrDefault(); } if (tmpl != null) { vmState.Add(new VmState { Id = vm.Id, Name = vm.Name, IsRunning = (vm.State == VmPowerState.Running), TemplateId = tmpl.Id }); } } state.Vms = vmState.ToArray(); } return(state); }