Ejemplo n.º 1
0
 public function view(Request $request, $id)
 {
     $service = Models\Service::find($id);
     if (!$service) {
         throw new NotFoundHttpException('No service by that ID was found.');
     }
     $options = Models\ServiceOptions::select('id', 'name', 'description', 'tag', 'docker_image')->where('parent_service', $service->id)->get();
     foreach ($options as &$opt) {
         $opt->variables = Models\ServiceVariables::where('option_id', $opt->id)->get();
     }
     return ['service' => $service, 'options' => $options];
 }
Ejemplo n.º 2
0
 public function delete($id)
 {
     $service = Models\Service::findOrFail($id);
     $servers = Models\Server::where('service', $service->id)->get();
     $options = Models\ServiceOptions::select('id')->where('parent_service', $service->id);
     if (count($servers) !== 0) {
         throw new DisplayException('You cannot delete a service that has servers associated with it.');
     }
     DB::beginTransaction();
     try {
         Models\ServiceVariables::whereIn('option_id', $options->get()->toArray())->delete();
         $options->delete();
         $service->delete();
         DB::commit();
     } catch (\Exception $ex) {
         DB::rollBack();
         throw $ex;
     }
 }
Ejemplo n.º 3
0
 public function create($service, array $data)
 {
     $service = Models\Service::findOrFail($service);
     $validator = Validator::make($data, ['name' => 'required|string|max:255', 'description' => 'required|string|min:1', 'tag' => 'required|string|max:255', 'executable' => 'sometimes|string|max:255', 'docker_image' => 'required|string|max:255', 'startup' => 'sometimes|string']);
     if ($validator->fails()) {
         throw new DisplayValidationException($validator->errors());
     }
     if (isset($data['executable']) && empty($data['executable'])) {
         $data['executable'] = null;
     }
     if (isset($data['startup']) && empty($data['startup'])) {
         $data['startup'] = null;
     }
     $option = new Models\ServiceOptions();
     $option->parent_service = $service->id;
     $option->fill($data);
     $option->save();
     return $option->id;
 }
Ejemplo n.º 4
0
 /**
  * Renders server settings page.
  *
  * @param  \Illuminate\Http\Request $request
  * @return \Illuminate\Contracts\View\View
  */
 public function getSettings(Request $request, $uuid)
 {
     $server = Models\Server::getByUUID($uuid);
     $allocation = Models\Allocation::findOrFail($server->allocation);
     $variables = Models\ServiceVariables::select('service_variables.*', DB::raw('COALESCE(server_variables.variable_value, service_variables.default_value) as a_serverValue'))->leftJoin('server_variables', 'server_variables.variable_id', '=', 'service_variables.id')->where('service_variables.option_id', $server->option)->where('server_variables.server_id', $server->id)->get();
     $service = Models\Service::select(DB::raw('IFNULL(service_options.executable, services.executable) as executable'))->leftJoin('service_options', 'service_options.parent_service', '=', 'services.id')->where('service_options.id', $server->option)->where('services.id', $server->service)->first();
     $serverVariables = ['{{SERVER_MEMORY}}' => $server->memory, '{{SERVER_IP}}' => $allocation->ip, '{{SERVER_PORT}}' => $allocation->port];
     $processed = str_replace(array_keys($serverVariables), array_values($serverVariables), $server->startup);
     foreach ($variables as &$variable) {
         $replace = $variable->user_viewable === 1 ? $variable->a_serverValue : '**';
         $processed = str_replace('{{' . $variable->env_variable . '}}', $replace, $processed);
     }
     return view('server.settings', ['server' => $server, 'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')->where('server_id', $server->id)->join('database_servers', 'database_servers.id', '=', 'databases.db_server')->get(), 'node' => Models\Node::find($server->node), 'variables' => $variables->where('user_viewable', 1), 'service' => $service, 'processedStartup' => $processed]);
 }
Ejemplo n.º 5
0
 private function addCoreService()
 {
     $this->service = Models\Service::create(['author' => 'ptrdctyl-v040-11e6-8b77-86f30ca893d3', 'name' => 'Voice Servers', 'description' => 'Voice servers such as Mumble and Teamspeak 3.', 'file' => 'voice', 'executable' => '', 'startup' => '']);
 }
 private function addCoreService()
 {
     $this->service = Models\Service::create(['author' => 'ptrdctyl-v040-11e6-8b77-86f30ca893d3', 'name' => 'Terraria', 'description' => 'Terraria is a land of adventure! A land of mystery! A land that\'s yours to shape, defend, and enjoy. Your options in Terraria are limitless. Are you an action gamer with an itchy trigger finger? A master builder? A collector? An explorer? There\'s something for everyone.', 'file' => 'terraria', 'executable' => 'TerrariaServer.exe', 'startup' => '-port {{SERVER_PORT}} -autocreate 2 -worldname World']);
 }
Ejemplo n.º 7
0
 /**
  * Adds a new server to the system.
  * @param   array  $data  An array of data descriptors for creating the server. These should align to the columns in the database.
  * @return  integer
  */
 public function create(array $data)
 {
     // Validate Fields
     $validator = Validator::make($data, ['owner' => 'required|email|exists:users,email', 'node' => 'required|numeric|min:1|exists:nodes,id', 'name' => 'required|regex:/^([\\w -]{4,35})$/', 'memory' => 'required|numeric|min:0', 'swap' => 'required|numeric|min:-1', 'io' => 'required|numeric|min:10|max:1000', 'cpu' => 'required|numeric|min:0', 'disk' => 'required|numeric|min:0', 'allocation' => 'numeric|exists:allocations,id|required_without:ip,port', 'ip' => 'required_without:allocation|ip', 'port' => 'required_without:allocation|numeric|min:1|max:65535', 'service' => 'required|numeric|min:1|exists:services,id', 'option' => 'required|numeric|min:1|exists:service_options,id', 'startup' => 'string', 'custom_image_name' => 'required_if:use_custom_image,on']);
     // Run validator, throw catchable and displayable exception if it fails.
     // Exception includes a JSON result of failed validation rules.
     if ($validator->fails()) {
         throw new DisplayValidationException($validator->errors());
     }
     // Get the User ID; user exists since we passed the 'exists:users,email' part of the validation
     $user = Models\User::select('id')->where('email', $data['owner'])->first();
     // Get Node Information
     $node = Models\Node::getByID($data['node']);
     // Verify IP & Port are a.) free and b.) assigned to the node.
     // We know the node exists because of 'exists:nodes,id' in the validation
     if (!isset($data['allocation'])) {
         $allocation = Models\Allocation::where('ip', $data['ip'])->where('port', $data['port'])->where('node', $data['node'])->whereNull('assigned_to')->first();
     } else {
         $allocation = Models\Allocation::where('id', $data['allocation'])->where('node', $data['node'])->whereNull('assigned_to')->first();
     }
     // Something failed in the query, either that combo doesn't exist, or it is in use.
     if (!$allocation) {
         throw new DisplayException('The selected IP/Port combination or Allocation ID is either already in use, or unavaliable for this node.');
     }
     // Validate those Service Option Variables
     // We know the service and option exists because of the validation.
     // We need to verify that the option exists for the service, and then check for
     // any required variable fields. (fields are labeled env_<env_variable>)
     $option = Models\ServiceOptions::where('id', $data['option'])->where('parent_service', $data['service'])->first();
     if (!$option) {
         throw new DisplayException('The requested service option does not exist for the specified service.');
     }
     // Load up the Service Information
     $service = Models\Service::find($option->parent_service);
     // Check those Variables
     $variables = Models\ServiceVariables::where('option_id', $data['option'])->get();
     $variableList = [];
     if ($variables) {
         foreach ($variables as $variable) {
             // Is the variable required?
             if (!$data['env_' . $variable->env_variable]) {
                 if ($variable->required === 1) {
                     throw new DisplayException('A required service option variable field (env_' . $variable->env_variable . ') was missing from the request.');
                 }
                 $variableList = array_merge($variableList, [['id' => $variable->id, 'env' => $variable->env_variable, 'val' => $variable->default_value]]);
                 continue;
             }
             // Check aganist Regex Pattern
             if (!is_null($variable->regex) && !preg_match($variable->regex, $data['env_' . $variable->env_variable])) {
                 throw new DisplayException('Failed to validate service option variable field (env_' . $variable->env_variable . ') aganist regex (' . $variable->regex . ').');
             }
             $variableList = array_merge($variableList, [['id' => $variable->id, 'env' => $variable->env_variable, 'val' => $data['env_' . $variable->env_variable]]]);
             continue;
         }
     }
     // Check Overallocation
     if (is_numeric($node->memory_overallocate) || is_numeric($node->disk_overallocate)) {
         $totals = Models\Server::select(DB::raw('SUM(memory) as memory, SUM(disk) as disk'))->where('node', $node->id)->first();
         // Check memory limits
         if (is_numeric($node->memory_overallocate)) {
             $newMemory = $totals->memory + $data['memory'];
             $memoryLimit = $node->memory * (1 + $node->memory_overallocate / 100);
             if ($newMemory > $memoryLimit) {
                 throw new DisplayException('The amount of memory allocated to this server would put the node over its allocation limits. This node is allowed ' . ($node->memory_overallocate + 100) . '% of its assigned ' . $node->memory . 'Mb of memory (' . $memoryLimit . 'Mb) of which ' . $totals->memory / $node->memory * 100 . '% (' . $totals->memory . 'Mb) is in use already. By allocating this server the node would be at ' . $newMemory / $node->memory * 100 . '% (' . $newMemory . 'Mb) usage.');
             }
         }
         // Check Disk Limits
         if (is_numeric($node->disk_overallocate)) {
             $newDisk = $totals->disk + $data['disk'];
             $diskLimit = $node->disk * (1 + $node->disk_overallocate / 100);
             if ($newDisk > $diskLimit) {
                 throw new DisplayException('The amount of disk allocated to this server would put the node over its allocation limits. This node is allowed ' . ($node->disk_overallocate + 100) . '% of its assigned ' . $node->disk . 'Mb of disk (' . $diskLimit . 'Mb) of which ' . $totals->disk / $node->disk * 100 . '% (' . $totals->disk . 'Mb) is in use already. By allocating this server the node would be at ' . $newDisk / $node->disk * 100 . '% (' . $newDisk . 'Mb) usage.');
             }
         }
     }
     DB::beginTransaction();
     try {
         $uuid = new UuidService();
         // Add Server to the Database
         $server = new Models\Server();
         $generatedUuid = $uuid->generate('servers', 'uuid');
         $server->fill(['uuid' => $generatedUuid, 'uuidShort' => $uuid->generateShort('servers', 'uuidShort', $generatedUuid), 'node' => $data['node'], 'name' => $data['name'], 'suspended' => 0, 'owner' => $user->id, 'memory' => $data['memory'], 'swap' => $data['swap'], 'disk' => $data['disk'], 'io' => $data['io'], 'cpu' => $data['cpu'], 'oom_disabled' => isset($data['oom_disabled']) ? true : false, 'allocation' => $allocation->id, 'service' => $data['service'], 'option' => $data['option'], 'startup' => $data['startup'], 'daemonSecret' => $uuid->generate('servers', 'daemonSecret'), 'username' => $this->generateSFTPUsername($data['name'])]);
         $server->save();
         // Mark Allocation in Use
         $allocation->assigned_to = $server->id;
         $allocation->save();
         // Add Variables
         $environmentVariables = [];
         $environmentVariables = array_merge($environmentVariables, ['STARTUP' => $data['startup']]);
         foreach ($variableList as $item) {
             $environmentVariables = array_merge($environmentVariables, [$item['env'] => $item['val']]);
             Models\ServerVariables::create(['server_id' => $server->id, 'variable_id' => $item['id'], 'variable_value' => $item['val']]);
         }
         $client = Models\Node::guzzleRequest($node->id);
         $client->request('POST', '/servers', ['headers' => ['X-Access-Token' => $node->daemonSecret], 'json' => ['uuid' => (string) $server->uuid, 'user' => $server->username, 'build' => ['default' => ['ip' => $allocation->ip, 'port' => (int) $allocation->port], 'ports' => [(string) $allocation->ip => [(int) $allocation->port]], 'env' => $environmentVariables, 'memory' => (int) $server->memory, 'swap' => (int) $server->swap, 'io' => (int) $server->io, 'cpu' => (int) $server->cpu, 'disk' => (int) $server->disk, 'image' => isset($data['custom_image_name']) ? $data['custom_image_name'] : $option->docker_image], 'service' => ['type' => $service->file, 'option' => $option->tag], 'keys' => [(string) $server->daemonSecret => $this->daemonPermissions], 'rebuild' => false]]);
         DB::commit();
         return $server->id;
     } catch (\GuzzleHttp\Exception\TransferException $ex) {
         DB::rollBack();
         throw new DisplayException('There was an error while attempting to connect to the daemon to add this server.', $ex);
     } catch (\Exception $ex) {
         DB::rollBack();
         Log:
         error($ex);
         throw $ex;
     }
 }
Ejemplo n.º 8
0
 private function addCoreService()
 {
     $this->service = Models\Service::create(['author' => 'ptrdctyl-v040-11e6-8b77-86f30ca893d3', 'name' => 'Source Engine', 'description' => 'Includes support for most Source Dedicated Server games.', 'file' => 'srcds', 'executable' => './srcds_run', 'startup' => '-game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} -strictportbind -norestart']);
 }
 private function addCoreService()
 {
     $this->service = Models\Service::create(['author' => 'ptrdctyl-v040-11e6-8b77-86f30ca893d3', 'name' => 'Minecraft', 'description' => 'Minecraft - the classic game from Mojang. With support for Vanilla MC, Spigot, and many others!', 'file' => 'minecraft', 'executable' => 'java', 'startup' => '-Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}']);
 }
Ejemplo n.º 10
0
 /**
  * Returns a JSON tree of all avaliable options for a given service.
  *
  * @param  \Illuminate\Http\Request $request
  * @return \Illuminate\Contracts\View\View
  */
 public function postNewServerServiceOptions(Request $request)
 {
     if (!$request->input('service')) {
         return response()->json(['error' => 'Missing service in request.'], 500);
     }
     $service = Models\Service::select('executable', 'startup')->where('id', $request->input('service'))->first();
     return response()->json(Models\ServiceOptions::select('id', 'name', 'docker_image')->where('parent_service', $request->input('service'))->orderBy('name', 'asc')->get());
 }
Ejemplo n.º 11
0
 public function newOption(Request $request, $service)
 {
     return view('admin.services.options.new', ['service' => Models\Service::findOrFail($service)]);
 }