private function buildAuthorizationsBox(DrydockBlueprint $blueprint) { $viewer = $this->getViewer(); $limit = 25; // If there are pending authorizations against this blueprint, make sure // we show them first. $pending_authorizations = id(new DrydockAuthorizationQuery())->setViewer($viewer)->withBlueprintPHIDs(array($blueprint->getPHID()))->withObjectStates(array(DrydockAuthorization::OBJECTAUTH_ACTIVE))->withBlueprintStates(array(DrydockAuthorization::BLUEPRINTAUTH_REQUESTED))->setLimit($limit)->execute(); $all_authorizations = id(new DrydockAuthorizationQuery())->setViewer($viewer)->withBlueprintPHIDs(array($blueprint->getPHID()))->withObjectStates(array(DrydockAuthorization::OBJECTAUTH_ACTIVE))->withBlueprintStates(array(DrydockAuthorization::BLUEPRINTAUTH_REQUESTED, DrydockAuthorization::BLUEPRINTAUTH_AUTHORIZED))->setLimit($limit)->execute(); $authorizations = mpull($pending_authorizations, null, 'getPHID') + mpull($all_authorizations, null, 'getPHID'); $authorization_list = id(new DrydockAuthorizationListView())->setUser($viewer)->setAuthorizations($authorizations)->setNoDataString(pht('No objects have active authorizations to use this blueprint.')); $id = $blueprint->getID(); $authorizations_uri = "blueprint/{$id}/authorizations/query/all/"; $authorizations_uri = $this->getApplicationURI($authorizations_uri); $authorizations_header = id(new PHUIHeaderView())->setHeader(pht('Active Authorizations'))->addActionLink(id(new PHUIButtonView())->setTag('a')->setHref($authorizations_uri)->setIconFont('fa-search')->setText(pht('View All'))); return id(new PHUIObjectBoxView())->setHeader($authorizations_header)->setObjectList($authorization_list); }
private function buildResourceBox(DrydockBlueprint $blueprint) { $viewer = $this->getViewer(); $resources = id(new DrydockResourceQuery())->setViewer($viewer)->withBlueprintPHIDs(array($blueprint->getPHID()))->withStatuses(array(DrydockResourceStatus::STATUS_PENDING, DrydockResourceStatus::STATUS_ACTIVE))->setLimit(100)->execute(); $resource_list = id(new DrydockResourceListView())->setUser($viewer)->setResources($resources)->render()->setNoDataString(pht('This blueprint has no active resources.')); $id = $blueprint->getID(); $resources_uri = "blueprint/{$id}/resources/query/all/"; $resources_uri = $this->getApplicationURI($resources_uri); $resource_header = id(new PHUIHeaderView())->setHeader(pht('Active Resources'))->addActionLink(id(new PHUIButtonView())->setTag('a')->setHref($resources_uri)->setIconFont('fa-search')->setText(pht('View All Resources'))); return id(new PHUIObjectBoxView())->setHeader($resource_header)->setObjectList($resource_list); }
private function loadFreeBindings(DrydockBlueprint $blueprint) { if ($this->freeBindings === null) { $viewer = PhabricatorUser::getOmnipotentUser(); $pool = id(new DrydockResourceQuery())->setViewer($viewer)->withBlueprintPHIDs(array($blueprint->getPHID()))->withStatuses(array(DrydockResourceStatus::STATUS_PENDING, DrydockResourceStatus::STATUS_OPEN, DrydockResourceStatus::STATUS_CLOSED))->execute(); $allocated_phids = array(); foreach ($pool as $resource) { $allocated_phids[] = $resource->getAttribute('almanacDevicePHID'); } $allocated_phids = array_fuse($allocated_phids); $services = $this->loadServices($blueprint); $bindings = $this->loadAllBindings($services); $free = array(); foreach ($bindings as $binding) { if (empty($allocated_phids[$binding->getPHID()])) { $free[] = $binding; } } $this->freeBindings = $free; } return $this->freeBindings; }
protected function newLease(DrydockBlueprint $blueprint) { return DrydockLease::initializeNewLease()->setAuthorizingPHID($blueprint->getPHID()); }
/** * Apply standard limits on resource allocation rate. * * @param DrydockBlueprint The blueprint requesting an allocation. * @return bool True if further allocations should be limited. */ protected function shouldLimitAllocatingPoolSize(DrydockBlueprint $blueprint) { // TODO: If this mechanism sticks around, these values should be // configurable by the blueprint implementation. // Limit on total number of active resources. $total_limit = 1; // Always allow at least this many allocations to be in flight at once. $min_allowed = 1; // Allow this fraction of allocating resources as a fraction of active // resources. $growth_factor = 0.25; $resource = new DrydockResource(); $conn_r = $resource->establishConnection('r'); $counts = queryfx_all($conn_r, 'SELECT status, COUNT(*) N FROM %T WHERE blueprintPHID = %s AND status != %s GROUP BY status', $resource->getTableName(), $blueprint->getPHID(), DrydockResourceStatus::STATUS_DESTROYED); $counts = ipull($counts, 'N', 'status'); $n_alloc = idx($counts, DrydockResourceStatus::STATUS_PENDING, 0); $n_active = idx($counts, DrydockResourceStatus::STATUS_ACTIVE, 0); $n_broken = idx($counts, DrydockResourceStatus::STATUS_BROKEN, 0); $n_released = idx($counts, DrydockResourceStatus::STATUS_RELEASED, 0); // If we're at the limit on total active resources, limit additional // allocations. $n_total = $n_alloc + $n_active + $n_broken + $n_released; if ($n_total >= $total_limit) { return true; } // If the number of in-flight allocations is fewer than the minimum number // of allowed allocations, don't impose a limit. if ($n_alloc < $min_allowed) { return false; } $allowed_alloc = (int) ceil($n_active * $growth_factor); // If the number of in-flight allocation is fewer than the number of // allowed allocations according to the pool growth factor, don't impose // a limit. if ($n_alloc < $allowed_alloc) { return false; } return true; }
private function loadFreeBindings(DrydockBlueprint $blueprint) { if ($this->freeBindings === null) { $viewer = PhabricatorUser::getOmnipotentUser(); $pool = id(new DrydockResourceQuery())->setViewer($viewer)->withBlueprintPHIDs(array($blueprint->getPHID()))->withStatuses(array(DrydockResourceStatus::STATUS_PENDING, DrydockResourceStatus::STATUS_ACTIVE, DrydockResourceStatus::STATUS_BROKEN, DrydockResourceStatus::STATUS_RELEASED))->execute(); $allocated_phids = array(); foreach ($pool as $resource) { $allocated_phids[] = $resource->getAttribute('almanacBindingPHID'); } $allocated_phids = array_fuse($allocated_phids); $services = $this->loadServices($blueprint); $bindings = $this->loadAllBindings($services); $free = array(); foreach ($bindings as $binding) { // Don't consider disabled bindings to be available. if ($binding->getIsDisabled()) { continue; } if (empty($allocated_phids[$binding->getPHID()])) { $free[] = $binding; } } $this->freeBindings = $free; } return $this->freeBindings; }
private function reclaimResources(DrydockBlueprint $blueprint, DrydockLease $lease) { $viewer = $this->getViewer(); $resources = id(new DrydockResourceQuery())->setViewer($viewer)->withBlueprintPHIDs(array($blueprint->getPHID()))->withStatuses(array(DrydockResourceStatus::STATUS_ACTIVE))->execute(); // TODO: We could be much smarter about this and try to release long-unused // resources, resources with many similar copies, old resources, resources // that are cheap to rebuild, etc. shuffle($resources); foreach ($resources as $resource) { if ($this->canReclaimResource($resource)) { $this->reclaimResource($resource, $lease); return $resource; } } return null; }