true, self::CONFIG_SERIALIZATION => array( 'attributes' => self::SERIALIZATION_JSON, ), ) + parent::getConfiguration(); } public function setAttribute($key, $value) { $this->attributes[$key] = $value; return $this; } public function getAttribute($key, $default = null) { return idx($this->attributes, $key, $default); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPHIDConstants::PHID_TYPE_DRYL); } public function getInterface($type) { return $this->getResource()->getInterface($this, $type); } public function getResource() { $this->assertActive(); if ($this->resource === null) { throw new Exception("Resource is not yet loaded."); } return $this->resource; } public function attachResource(DrydockResource $resource) { $this->assertActive(); $this->resource = $resource; return $this; } public function loadResource() { $this->assertActive(); return id(new DrydockResource())->loadOneWhere( 'id = %d', $this->getResourceID()); } public function release() { // TODO: Insert a cleanup task into the taskmaster queue. $this->setStatus(DrydockLeaseStatus::STATUS_RELEASED); $this->save(); $this->resource = null; return $this; } private function assertActive() { if ($this->status != DrydockLeaseStatus::STATUS_ACTIVE) { throw new Exception( "Lease is not active! You can not interact with resources through ". "an inactive lease."); } } public function waitUntilActive() { $this->reload(); while (true) { switch ($this->status) { case DrydockLeaseStatus::STATUS_ACTIVE: break 2; case DrydockLeaseStatus::STATUS_RELEASED: case DrydockLeaseStatus::STATUS_EXPIRED: case DrydockLeaseStatus::STATUS_BROKEN: throw new Exception("Lease will never become active!"); case DrydockLeaseStatus::STATUS_PENDING: break; } sleep(2); $this->reload(); } $this->attachResource($this->loadResource()); return $this; } }