public function getView(Request $request, $id) { $server = Models\Server::select('servers.*', 'nodes.name as a_nodeName', 'users.email as a_ownerEmail', 'locations.long as a_locationName', 'services.name as a_serviceName', DB::raw('IFNULL(service_options.executable, services.executable) as a_serviceExecutable'), 'service_options.docker_image', 'service_options.name as a_servceOptionName', 'allocations.ip', 'allocations.port', 'allocations.ip_alias')->join('nodes', 'servers.node', '=', 'nodes.id')->join('users', 'servers.owner', '=', 'users.id')->join('locations', 'nodes.location', '=', 'locations.id')->join('services', 'servers.service', '=', 'services.id')->join('service_options', 'servers.option', '=', 'service_options.id')->join('allocations', 'servers.allocation', '=', 'allocations.id')->where('servers.id', $id)->first(); if (!$server) { return abort(404); } return view('admin.servers.view', ['server' => $server, 'assigned' => Models\Allocation::where('assigned_to', $id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(), 'unassigned' => Models\Allocation::where('node', $server->node)->whereNull('assigned_to')->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(), 'startup' => Models\ServiceVariables::select('service_variables.*', 'server_variables.variable_value as a_serverValue')->join('server_variables', 'server_variables.variable_id', '=', 'service_variables.id')->where('service_variables.option_id', $server->option)->where('server_variables.server_id', $server->id)->get(), '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(), 'db_servers' => Models\DatabaseServer::all()]); }
/** * Returns an array of each server ID that the user has access to. * * @return array */ public static function accessServers() { $access = []; $union = self::select('server_id')->where('user_id', self::$user->id); $select = Server::select('id')->where('owner', self::$user->id)->union($union)->get(); foreach ($select as &$select) { $access = array_merge($access, [$select->id]); } return $access; }
/** * Run the migrations. * * @return void */ public function up() { Schema::table('servers', function (Blueprint $table) { $table->string('image')->after('daemonSecret'); }); // Populate the column $servers = Server::select('servers.id', 'service_options.docker_image as s_optionImage')->join('service_options', 'service_options.id', '=', 'servers.option')->get(); foreach ($servers as $server) { $server->image = $server->s_optionImage; $server->save(); } }
public function getView(Request $request, $id) { return view('admin.users.view', ['user' => User::findOrFail($id), 'servers' => Server::select('servers.*', 'nodes.name as nodeName', 'locations.long as location')->join('nodes', 'servers.node', '=', 'nodes.id')->join('locations', 'nodes.location', '=', 'locations.id')->where('owner', $id)->get()]); }
/** * 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; } }
public function getOption(Request $request, $service, $option) { $opt = Models\ServiceOptions::findOrFail($option); return view('admin.services.options.view', ['service' => Models\Service::findOrFail($opt->parent_service), 'option' => $opt, 'variables' => Models\ServiceVariables::where('option_id', $option)->get(), 'servers' => Models\Server::select('servers.*', 'users.email as a_ownerEmail')->join('users', 'users.id', '=', 'servers.owner')->where('option', $option)->paginate(10)]); }
public function getView(Request $request, $id) { $node = Models\Node::findOrFail($id); $allocations = []; $alloc = Models\Allocation::select('ip', 'port', 'assigned_to')->where('node', $node->id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(); if ($alloc) { foreach ($alloc as &$alloc) { if (!array_key_exists($alloc->ip, $allocations)) { $allocations[$alloc->ip] = [['port' => $alloc->port, 'assigned_to' => $alloc->assigned_to]]; } else { array_push($allocations[$alloc->ip], ['port' => $alloc->port, 'assigned_to' => $alloc->assigned_to]); } } } return view('admin.nodes.view', ['node' => $node, 'servers' => Models\Server::select('servers.*', 'users.email as a_ownerEmail', 'services.name as a_serviceName')->join('users', 'users.id', '=', 'servers.owner')->join('services', 'services.id', '=', 'servers.service')->where('node', $id)->paginate(10), 'stats' => Models\Server::select(DB::raw('SUM(memory) as memory, SUM(disk) as disk'))->where('node', $node->id)->first(), 'locations' => Models\Location::all(), 'allocations' => json_decode(json_encode($allocations), false)]); }