Example #1
0
        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());
        }
Example #2
0
        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));
        }
Example #3
0
        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));
        }
Example #4
0
        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);
        }
Example #5
0
        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)));
        }
Example #6
0
        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));
        }
Example #7
0
        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));
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
        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);
        }