/** * Gets the User Entity for the current request * * @return User|null Returns the User entity for the current Request */ public function getUser() { if (empty($this->_user) && $this->user->getId()) { $this->_user = User::findPk($this->user->getId()); } return $this->_user; }
public function xRequestResultAction() { $this->request->defineParams(array('requests' => array('type' => 'json'), 'decision')); if (!in_array($this->getParam('decision'), array(FarmLease::STATUS_APPROVE, FarmLease::STATUS_DECLINE))) { throw new Scalr_Exception_Core('Wrong status'); } foreach ($this->getParam('requests') as $id) { $req = $this->db->GetRow('SELECT * FROM farm_lease_requests WHERE id = ? LIMIT 1', array($id)); if ($req) { $dbFarm = DBFarm::LoadByID($req['farm_id']); $this->user->getPermissions()->validate($dbFarm); $this->db->Execute('UPDATE farm_lease_requests SET status = ?, answer_comment = ?, answer_user_id = ? WHERE id = ?', array($this->getParam('decision'), $this->getParam('comment'), $this->user->getId(), $id)); try { $mailer = Scalr::getContainer()->mailer; if ($dbFarm->ownerId) { $user = Entity\Account\User::findPk($dbFarm->ownerId); if (\Scalr::config('scalr.auth_mode') == 'ldap') { $email = $user->getSetting(Entity\Account\User\UserSetting::NAME_LDAP_EMAIL); if (!$email) { $email = $user->email; } } else { $email = $user->email; } $mailer->addTo($email); } else { $mailer = null; } } catch (Exception $e) { $mailer = null; } if ($this->getParam('decision') == FarmLease::STATUS_APPROVE) { if ($req['request_days'] > 0) { $dt = $dbFarm->GetSetting(Entity\FarmSetting::LEASE_TERMINATE_DATE); $dt = new DateTime($dt); $dt->add(new DateInterval('P' . $req['request_days'] . 'D')); $dbFarm->SetSetting(Entity\FarmSetting::LEASE_TERMINATE_DATE, $dt->format('Y-m-d H:i:s')); $dbFarm->SetSetting(Entity\FarmSetting::LEASE_NOTIFICATION_SEND, null); if ($mailer) { $mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/farm_lease_non_standard_approve.eml', array('{{farm_name}}' => $dbFarm->Name, '{{user_name}}' => $this->user->getEmail(), '{{comment}}' => $this->getParam('comment'), '{{date}}' => $dt->format('M j, Y'), '{{envName}}' => $dbFarm->GetEnvironmentObject()->name, '{{envId}}' => $dbFarm->GetEnvironmentObject()->id)); } } else { $dbFarm->SetSetting(Entity\FarmSetting::LEASE_STATUS, ''); $dbFarm->SetSetting(Entity\FarmSetting::LEASE_TERMINATE_DATE, ''); $dbFarm->SetSetting(Entity\FarmSetting::LEASE_NOTIFICATION_SEND, ''); if ($mailer) { $mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/farm_lease_non_standard_forever.eml', array('{{farm_name}}' => $dbFarm->Name, '{{user_name}}' => $this->user->getEmail(), '{{comment}}' => $this->getParam('comment'), '{{envName}}' => $dbFarm->GetEnvironmentObject()->name, '{{envId}}' => $dbFarm->GetEnvironmentObject()->id)); } } } else { $dt = new DateTime($dbFarm->GetSetting(Entity\FarmSetting::LEASE_TERMINATE_DATE)); SettingEntity::increase(SettingEntity::LEASE_DECLINED_REQUEST); if ($mailer) { $mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/farm_lease_non_standard_decline.eml', array('{{farm_name}}' => $dbFarm->Name, '{{user_name}}' => $this->user->getEmail(), '{{date}}' => $dt->format('M j, Y'), '{{comment}}' => $this->getParam('comment'), '{{envName}}' => $dbFarm->GetEnvironmentObject()->name, '{{envId}}' => $dbFarm->GetEnvironmentObject()->id)); } } } } $this->response->success(); }
/** * LockedException * * @param int $lockedBy Id of User that add a lock to the object * @param mixed $object optional Locked object * @param string $comment optional Lock comment * @param int $code optional The Exception code * @param Exception $previous optional The previous exception used for the exception chaining */ public function __construct($lockedBy, $object = null, $comment = '', $code = 0, Exception $previous = null) { $this->lockedBy = $lockedBy; $this->object = $object; /* @var $user User */ $user = User::findPk($lockedBy); $userName = empty($user) ? $lockedBy : $user->email; if (!empty($comment)) { $comment = " with comment: '{$comment}'"; } if (is_object($object)) { $object = array_pop(preg_split('\\', get_class($object))); } parent::__construct((empty($object) ? "Locked" : "{$object} locked") . " by {$userName}{$comment}", $code, $previous); }
/** * LockedException * * @param int $lockedBy Id of User that add a lock to the object * @param mixed $object optional Locked object * @param string $comment optional Lock comment * @param int $code optional The Exception code * @param Exception $previous optional The previous exception used for the exception chaining */ public function __construct($lockedBy, $object = null, $comment = '', $code = 0, Exception $previous = null) { if (is_array($object)) { throw new InvalidArgumentException("Second argument can not be an array"); } $this->lockedBy = $lockedBy; $this->object = $object; /* @var $user User */ $user = User::findPk($lockedBy); $userName = empty($user) ? $lockedBy : $user->email; if (!empty($comment)) { $comment = " with comment: '{$comment}'"; } if (is_object($object)) { $nameParts = explode('\\', get_class($object)); $object = array_pop($nameParts); } parent::__construct((empty($object) ? "Locked" : "{$object} locked") . " by {$userName}{$comment}", $code, $previous); }
/** * Generate data for ApiTestCaseV2 * * @param string $fixtures patch to fixtures directory * @return array * @throws \Scalr\System\Config\Exception\YamlException */ public static function dataFixtures($fixtures) { // set config static::$testUserId = \Scalr::config('scalr.phpunit.userid'); static::$user = User::findPk(static::$testUserId); static::$testEnvId = \Scalr::config('scalr.phpunit.envid'); static::$env = Environment::findPk(static::$testEnvId); $data = []; foreach (new DirectoryIterator($fixtures) as $fileInfo) { if ($fileInfo->isFile()) { $class = __NAMESPACE__ . '\\' . ucfirst($fileInfo->getBasename('.yaml')); if (class_exists($class)) { /* @var $object TestDataFixtures */ $object = new $class(Yaml::load($fileInfo->getPathname())->toArray()); $object->prepareTestData(); $data = array_merge($data, $object->preparePathInfo()); } } } return $data; }
/** * {@inheritdoc} * @see \Scalr\System\Zmq\Cron\TaskInterface::worker() */ public function worker($request) { //Warming up static DI cache \Scalr::getContainer()->warmup(); // Reconfigure observers \Scalr::ReconfigureObservers(); try { $dbFarm = DBFarm::LoadByID($request->farmId); $curDate = new DateTime(); $tdValue = $dbFarm->GetSetting(Entity\FarmSetting::LEASE_TERMINATE_DATE); if ($tdValue) { $td = new DateTime($tdValue); if ($td < $curDate) { //Terminates farm SettingEntity::increase(SettingEntity::LEASE_TERMINATE_FARM); //Ajdusts both account & environment for the audit log \Scalr::getContainer()->auditlogger->setAccountId($dbFarm->ClientID)->setAccountId($dbFarm->EnvID); \Scalr::FireEvent($request->farmId, new FarmTerminatedEvent(0, 1, false, 1, true, null)); $this->log('INFO', sprintf('Farm: %s [ID: %d] was terminated by lease manager', $dbFarm->Name, $dbFarm->ID)); } else { // only inform user $days = $td->diff($curDate)->days; $notifications = json_decode($dbFarm->GetSetting(Entity\FarmSetting::LEASE_NOTIFICATION_SEND), true); $governance = new Scalr_Governance($dbFarm->EnvID); $settings = $governance->getValue(Scalr_Governance::CATEGORY_GENERAL, Scalr_Governance::GENERAL_LEASE, 'notifications'); if (is_array($settings)) { foreach ($settings as $n) { if (!$notifications[$n['key']] && $n['period'] >= $days) { $mailer = \Scalr::getContainer()->mailer; $tdHuman = Scalr_Util_DateTime::convertDateTime($td, $dbFarm->GetSetting(Entity\FarmSetting::TIMEZONE), 'M j, Y'); /* @var $user Entity\Account\User */ if ($n['to'] == 'owner') { if ($dbFarm->ownerId) { $user = Entity\Account\User::findPk($dbFarm->ownerId); } else { $user = Entity\Account\User::findOne([['accountId' => $dbFarm->ClientID], ['type' => Entity\Account\User::TYPE_ACCOUNT_OWNER]]); } if (\Scalr::config('scalr.auth_mode') == 'ldap') { $email = $user->getSetting(Entity\Account\User\UserSetting::NAME_LDAP_EMAIL); if (!$email) { $email = $user->email; } } else { $email = $user->email; } $mailer->addTo($email); } else { foreach (explode(',', $n['emails']) as $email) { $mailer->addTo(trim($email)); } } $mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/farm_lease_terminate.eml.php', array('terminateDate' => $tdHuman, 'farm' => $dbFarm->Name, 'envName' => $dbFarm->GetEnvironmentObject()->name, 'envId' => $dbFarm->GetEnvironmentObject()->id, 'showOwnerWarning' => !$dbFarm->ownerId)); $notifications[$n['key']] = 1; $dbFarm->SetSetting(Entity\FarmSetting::LEASE_NOTIFICATION_SEND, json_encode($notifications)); $this->log('INFO', "Notification was sent by key: %s about farm: %s [ID: %d] by lease manager", $n['key'], $dbFarm->Name, $dbFarm->ID); } } } } } } catch (Exception $e) { throw $e; } return $request; }
/** * Setups test user, environment and API key * * @beforeClass * * @throws \Scalr\Exception\ModelException */ public static function setUpBeforeClass() { static::$testUserId = \Scalr::config('scalr.phpunit.userid'); static::$user = User::findPk(static::$testUserId); static::$testEnvId = \Scalr::config('scalr.phpunit.envid'); static::$env = Environment::findPk(static::$testEnvId); $apiKeyName = static::getTestName(); $apiKeyEntity = ApiKeyEntity::findOne([['name' => $apiKeyName], ['userId' => static::$testUserId]]); if (empty($apiKeyEntity)) { $apiKeyEntity = new ApiKeyEntity(static::$testUserId); $apiKeyEntity->name = $apiKeyName; $apiKeyEntity->save(); } static::$apiKeyEntity = $apiKeyEntity; }
/** * Check whether the user has either READ or WRITE access to the specified object * * * @param object $object * The object to check * * @param Entity\Account\User|int $user * Either the User Entity or its identifier * * @param Entity\Account\Environment|int $enviroment optional * Either the Environment Entity or its identifier * * @param bool $modify optional * Whether it should check MODIFY permission. By default it checks READ permission. * * @return bool Returns TRUE if the user has access to the specified object * @throws \InvalidArgumentException * @throws NotYetImplementedException */ public function hasAccessTo($object, $user, $enviroment = null, $modify = null) { $modify = $modify ?: false; if (is_int($user)) { $user = Entity\Account\User::findPk($user); } if ($enviroment !== null && is_int($enviroment)) { $enviroment = Entity\Account\Environment::findPk($enviroment); if (!$enviroment) { throw new \InvalidArgumentException(sprintf("Could not find the Environment by id: %d", func_get_arg(2))); } } if (!$user instanceof Entity\Account\User) { throw new \InvalidArgumentException(sprintf('Second argument should be instance of \\Scalr\\Model\\Entity\\Account\\User class.')); } if ($enviroment !== null && !$enviroment instanceof Entity\Account\Environment) { throw new \InvalidArgumentException(sprintf('Third argument should be instance of \\Scalr\\Model\\Entity\\Account\\Environment class.')); } if (!is_object($object)) { throw new \InvalidArgumentException(sprintf("The first argument must be an object.")); } if ($object instanceof AccessPermissionsInterface) { return $object->hasAccessPermissions($user, $enviroment, $modify); } throw new NotYetImplementedException(sprintf("%s nothing knows about %s class", __METHOD__, get_class($object))); }
/** * Transform entity of type MESSAGE for client-side (view, edit) * * @param Announcement $announcement * @return array Contains keys `id`, `accountId`, `added`, `title`, `msg`, `user`. */ private function prepareDataForList(Announcement $announcement) { $obj = ['id' => $announcement->id, 'accountId' => $announcement->accountId, 'added' => Scalr_Util_DateTime::convertTz($announcement->added, 'M d, Y G:i'), 'title' => $announcement->title, 'msg' => $announcement->msg]; /* @var $user Scalr\Model\Entity\Account\User */ $user = User::findPk($announcement->createdById); if ($user) { $obj['user'] = ['name' => $user->fullName, 'email' => $user->email]; } else { $obj['user'] = ['name' => '#' . $announcement->createdById, 'email' => $announcement->createdByEmail]; } return $obj; }
/** * Add test environment, test Acl, setups test user, environment and API key */ public static function setUpBeforeClass() { if (!Scalr::getContainer()->config->defined('scalr.phpunit.apiv2')) { static::markTestIncomplete('phpunit apiv2 configurations is invalid'); } if (Scalr::getContainer()->config->defined('scalr.phpunit.apiv2.params.max_results')) { static::$maxResults = Scalr::config('scalr.phpunit.apiv2.params.max_results'); } static::$testUserId = Scalr::config('scalr.phpunit.apiv2.userid'); static::$user = User::findPk(static::$testUserId); static::$testUserType = static::$user->type; static::$testEnvId = Scalr::config('scalr.phpunit.apiv2.envid'); static::$env = Environment::findPk(static::$testEnvId); if (empty(static::$user) || empty(static::$env)) { static::markTestIncomplete('Either test environment or user is invalid.'); } $apiKeyName = static::getTestName(); $apiKeyEntity = ApiKeyEntity::findOne([['name' => $apiKeyName], ['userId' => static::$testUserId]]); if (empty($apiKeyEntity)) { $apiKeyEntity = new ApiKeyEntity(static::$testUserId); $apiKeyEntity->name = $apiKeyName; $apiKeyEntity->save(); } static::$apiKeyEntity = $apiKeyEntity; static::$defaultAcl = Scalr::getContainer()->acl; static::$data = [static::$testEnvId => []]; if (empty(static::$fullAccessAcl)) { static::$fullAccessAcl = new ApiTestAcl(); static::$fullAccessAcl->setDb(Scalr::getContainer()->adodb); static::$fullAccessAcl->createTestAccountRole(static::$user->getAccountId(), static::getTestName(ApiFixture::ACL_FULL_ACCESS), ApiTestAcl::ROLE_ID_FULL_ACCESS); static::$fullAccessAcl->aclType = ApiFixture::ACL_FULL_ACCESS; } if (empty(static::$readOnlyAccessAcl)) { static::$readOnlyAccessAcl = new ApiTestAcl(); static::$readOnlyAccessAcl->setDb(Scalr::getContainer()->adodb); static::$readOnlyAccessAcl->createTestAccountRole(static::$user->getAccountId(), static::getTestName(ApiFixture::ACL_READ_ONLY_ACCESS), ApiTestAcl::ROLE_ID_READ_ONLY_ACCESS); static::$readOnlyAccessAcl->aclType = ApiFixture::ACL_READ_ONLY_ACCESS; } }
/** * Launches server * * @param \ServerCreateInfo $ServerCreateInfo optional The server create info * @param \DBServer $DBServer optional The DBServer object * @param bool $delayed optional * @param integer|array $reason optional * @param \Scalr_Account_User|int $user optional The Scalr_Account_User object or its unique identifier * @return DBServer|null Returns the DBServer object on cussess or null otherwise */ public static function LaunchServer(ServerCreateInfo $ServerCreateInfo = null, DBServer $DBServer = null, $delayed = false, $reason = 0, $user = null) { $db = self::getDb(); $farm = null; //Ensures handling identifier of the user instead of the object if ($user !== null && !$user instanceof \Scalr_Account_User) { try { $user = Scalr_Account_User::init()->loadById(intval($user)); } catch (\Exception $e) { } } if (!$DBServer && $ServerCreateInfo) { $ServerCreateInfo->SetProperties(array(SERVER_PROPERTIES::SZR_KEY => self::GenerateRandomKey(40), SERVER_PROPERTIES::SZR_KEY_TYPE => SZR_KEY_TYPE::ONE_TIME)); $DBServer = DBServer::Create($ServerCreateInfo, false, true); } elseif (!$DBServer && !$ServerCreateInfo) { // incorrect arguments self::getContainer()->logger(LOG_CATEGORY::FARM)->error(sprintf("Cannot create server")); return null; } else { if ($DBServer && empty($DBServer->cloudLocation)) { trigger_error('Cloud location is missing in DBServer', E_USER_WARNING); } } $propsToSet = array(); if ($user instanceof \Scalr_Account_User) { $propsToSet[SERVER_PROPERTIES::LAUNCHED_BY_ID] = $user->id; $propsToSet[SERVER_PROPERTIES::LAUNCHED_BY_EMAIL] = $user->getEmail(); } //We should keep role_id and farm_role_id in server properties to use in cost analytics if (!empty($DBServer->farmRoleId)) { $propsToSet[SERVER_PROPERTIES::FARM_ROLE_ID] = $DBServer->farmRoleId; $propsToSet[SERVER_PROPERTIES::ROLE_ID] = $DBServer->farmRoleId ? $DBServer->GetFarmRoleObject()->RoleID : 0; } try { // Ensures the farm object will be fetched as correctly as possible $farm = $DBServer->farmId ? $DBServer->GetFarmObject() : null; $farmRole = $DBServer->farmRoleId ? $DBServer->GetFarmRoleObject() : null; if (!$farmRole instanceof DBFarmRole) { $farmRole = null; } else { if (!$farm instanceof DBFarm) { // Gets farm through FarmRole object in this case $farm = $farmRole->GetFarmObject(); } } if ($farm instanceof DBFarm) { $propsToSet[SERVER_PROPERTIES::FARM_CREATED_BY_ID] = $farm->ownerId ?: $farm->GetSetting(Entity\FarmSetting::CREATED_BY_ID); $propsToSet[SERVER_PROPERTIES::FARM_CREATED_BY_EMAIL] = $farm->ownerId ? Entity\Account\User::findPk($farm->ownerId)->email : $farm->GetSetting(Entity\FarmSetting::CREATED_BY_EMAIL); $projectId = $farm->GetSetting(Entity\FarmSetting::PROJECT_ID); if (!empty($projectId)) { try { $projectEntity = ProjectEntity::findPk($projectId); if ($projectEntity instanceof ProjectEntity) { /* @var $projectEntity ProjectEntity */ $ccId = $projectEntity->ccId; } else { $projectId = null; } } catch (Exception $e) { $projectId = null; } } $propsToSet[SERVER_PROPERTIES::FARM_PROJECT_ID] = $projectId; } if ($farmRole instanceof DBFarmRole) { $role = $farmRole->GetRoleObject(); $DBServer->isScalarized = $role->isScalarized; if (!$DBServer->isScalarized) { $propsToSet[SERVER_PROPERTIES::SZR_VESION] = ''; } $DBServer->Save(); } if (!empty($ccId)) { $propsToSet[SERVER_PROPERTIES::ENV_CC_ID] = $ccId; } elseif ($DBServer->envId && ($environment = $DBServer->GetEnvironmentObject()) instanceof Scalr_Environment) { $propsToSet[SERVER_PROPERTIES::ENV_CC_ID] = $environment->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID); } } catch (Exception $e) { self::getContainer()->logger(LOG_CATEGORY::FARM)->error(sprintf("Could not load related object for recently created server %s. It says: %s", $DBServer->serverId, $e->getMessage())); } if (!empty($propsToSet)) { $DBServer->SetProperties($propsToSet); } $fnGetReason = function ($reasonId) { $args = func_get_args(); $args[0] = DBServer::getLaunchReason($reasonId); return [call_user_func_array('sprintf', $args), $reasonId]; }; if ($reason) { list($reasonMsg, $reasonId) = is_array($reason) ? call_user_func_array($fnGetReason, $reason) : $fnGetReason($reason); $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_REASON => $reasonMsg, SERVER_PROPERTIES::LAUNCH_REASON_ID => $reasonId]); } else { $reasonMsg = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON); $reasonId = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON_ID); } if ($delayed) { $DBServer->updateStatus(SERVER_STATUS::PENDING_LAUNCH); return $DBServer; } if ($ServerCreateInfo && $ServerCreateInfo->roleId) { $dbRole = DBRole::loadById($ServerCreateInfo->roleId); if ($dbRole->generation == 1) { $DBServer->updateStatus(SERVER_STATUS::PENDING_LAUNCH); $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ERROR => "ami-scripts servers no longer supported", SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]); return $DBServer; } } // Limit amount of pending servers if ($DBServer->isOpenstack()) { $config = self::getContainer()->config; if ($config->defined("scalr.{$DBServer->platform}.pending_servers_limit")) { $pendingServersLimit = $config->get("scalr.{$DBServer->platform}.pending_servers_limit"); $pendingServers = $db->GetOne("SELECT COUNT(*) FROM servers WHERE platform=? AND status=? AND server_id != ?", array($DBServer->platform, SERVER_STATUS::PENDING, $DBServer->serverId)); if ($pendingServers >= $pendingServersLimit) { self::getContainer()->logger("SERVER_LAUNCH")->warn("{$pendingServers} servers in PENDING state on {$DBServer->platform}. Limit is: {$pendingServersLimit}. Waiting."); $DBServer->updateStatus(SERVER_STATUS::PENDING_LAUNCH); $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]); return $DBServer; } else { self::getContainer()->logger("SERVER_LAUNCH")->warn("{$pendingServers} servers in PENDING state on {$DBServer->platform}. Limit is: {$pendingServersLimit}. Launching server."); } } } try { $account = Scalr_Account::init()->loadById($DBServer->clientId); $account->validateLimit(Scalr_Limits::ACCOUNT_SERVERS, 1); PlatformFactory::NewPlatform($DBServer->platform)->LaunchServer($DBServer); $DBServer->status = SERVER_STATUS::PENDING; $DBServer->Save(); try { $DBServer->getServerHistory()->markAsLaunched($reasonMsg, $reasonId); $DBServer->updateTimelog('ts_launched'); if ($DBServer->imageId) { //Update Image last used date /* @var $server Entity\Server */ $server = Entity\Server::findPk($DBServer->serverId); $image = $server->getImage(); if ($image) { $image->update(['dtLastUsed' => new DateTime()]); } if ($server->farmRoleId && empty($server->getFarmRole())) { trigger_error(sprintf("Call to a member function getRole() on null. Server: %s, FarmRole: %d", $server->serverId, $server->farmRoleId), E_USER_WARNING); } if ($server->farmRoleId && !empty($server->getFarmRole()->getRole())) { //Update Role last used date $server->getFarmRole()->getRole()->update(['lastUsed' => new DateTime()]); } } } catch (Exception $e) { self::getContainer()->logger('SERVER_HISTORY')->error(sprintf("Cannot update servers history: {$e->getMessage()}")); } } catch (Exception $e) { self::getContainer()->logger(LOG_CATEGORY::FARM)->error(new FarmLogMessage($DBServer, sprintf("Cannot launch server on '%s' platform: %s", !empty($DBServer->platform) ? $DBServer->platform : null, $e->getMessage()))); $existingLaunchError = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ERROR); $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ERROR => $e->getMessage(), SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]); $DBServer->updateStatus(SERVER_STATUS::PENDING_LAUNCH); if ($DBServer->farmId && !$existingLaunchError) { self::FireEvent($DBServer->farmId, new InstanceLaunchFailedEvent($DBServer, $e->getMessage())); } } if ($DBServer->status == SERVER_STATUS::PENDING) { self::FireEvent($DBServer->farmId, new BeforeInstanceLaunchEvent($DBServer)); $DBServer->SetProperty(SERVER_PROPERTIES::LAUNCH_ERROR, ""); } return $DBServer; }
/** * Setups test user, environment and API key * * @throws \Scalr\Exception\ModelException */ public static function setUpBeforeClass() { static::$testUserId = \Scalr::config('scalr.phpunit.userid'); static::$user = User::findPk(static::$testUserId); static::$testEnvId = \Scalr::config('scalr.phpunit.envid'); static::$env = Environment::findPk(static::$testEnvId); if (empty(static::$user) || empty(static::$env)) { static::markTestIncomplete('Either test environment or user is invalid.'); } $apiKeyName = static::getTestName(); $apiKeyEntity = ApiKeyEntity::findOne([['name' => $apiKeyName], ['userId' => static::$testUserId]]); if (empty($apiKeyEntity)) { $apiKeyEntity = new ApiKeyEntity(static::$testUserId); $apiKeyEntity->name = $apiKeyName; $apiKeyEntity->save(); } static::$apiKeyEntity = $apiKeyEntity; static::changeLoggerConfiguration(); }
/** * @param JsonData $ids * @param string $action * @param int $ownerId */ public function xGroupActionHandlerAction(JsonData $ids, $action, $ownerId = null) { $processed = array(); $errors = array(); $needUpdateFarmOwner = false; $actionMsg = ''; $ids = (array) $ids; if ($ownerId && !User::findOne([['id' => $ownerId], ['accountId' => $this->user->getAccountId()]])) { $ownerId = null; } foreach ($ids as $userId) { try { $user = Scalr_Account_User::init(); $user->loadById($userId); switch ($action) { case 'delete': $actionMsg = 'removed'; if ($this->user->canRemoveUser($user)) { $ownedFarms = Farm::findByOwnerId($user->id); if ($ownedFarms->count() > 0) { if ($ownerId) { /* @var $newOwner User */ $newOwner = User::findPk($ownerId); /* @var $u User */ $u = User::findPk($this->user->getId()); foreach ($ownedFarms as $farm) { /* @var $farm Farm */ FarmSetting::addOwnerHistory($farm, $newOwner, $u); $farm->ownerId = $ownerId; $farm->save(); } } else { $needUpdateFarmOwner = true; throw new Exception("You can't delete owner of the Farm"); } } $user->delete(); $processed[] = $user->getId(); } else { throw new Exception('Insufficient permissions to remove user'); } break; case 'activate': $actionMsg = 'activated'; if ($this->user->getId() !== $user->getId() && $this->user->canEditUser($user)) { if ($user->status == Scalr_Account_User::STATUS_ACTIVE) { throw new Scalr_Exception_Core('User(s) has already been activated'); } $user->status = Scalr_Account_User::STATUS_ACTIVE; $user->save(); $processed[] = $user->getId(); } else { throw new Scalr_Exception_Core('Insufficient permissions to activate user'); } break; case 'deactivate': $actionMsg = 'deactivated'; if ($this->user->getId() !== $user->getId() && $this->user->canEditUser($user)) { if ($user->status == Scalr_Account_User::STATUS_INACTIVE) { throw new Scalr_Exception_Core('User(s) has already been suspended'); } $user->status = Scalr_Account_User::STATUS_INACTIVE; $user->save(); $processed[] = $user->getId(); } else { throw new Scalr_Exception_Core('Insufficient permissions to deactivate user'); } break; } } catch (Exception $e) { $errors[] = $e->getMessage(); } } $num = count($ids); if (count($processed) == $num) { $this->response->success("Selected user(s) successfully {$actionMsg}"); } else { array_walk($errors, function (&$item) { $item = '- ' . $item; }); $this->response->warning(sprintf("Successfully {$actionMsg} only %d from %d users. \nFollowing errors occurred:\n%s", count($processed), $num, join(array_unique($errors), "\n"))); } $this->response->data(['processed' => $processed]); if ($needUpdateFarmOwner) { $users = []; foreach (User::findByAccountId($this->user->getAccountId()) as $user) { /* @var $user User */ if (in_array($user->id, $ids)) { continue; } $users[] = ['id' => $user->id, 'email' => $user->email]; } $this->response->data(['needUpdateFarmOwner' => $needUpdateFarmOwner, 'usersList' => $users]); } }
/** * {@inheritdoc} * @see \Scalr\System\Zmq\Cron\TaskInterface::worker() */ public function worker($request) { $db = \Scalr::getDb(); //Warming up static DI cache \Scalr::getContainer()->warmup(); // Reconfigure observers \Scalr::ReconfigureObservers(); $bundleTask = BundleTask::LoadById($request->bundleTaskId); if (!$bundleTask instanceof BundleTask) { $this->getLogger()->fatal("Could not load bundle task id: %s", $request->bundleTaskId); return false; } else { $this->bundleTask = $bundleTask; $this->getLogger()->info("Processing bundle task id: %d status: %s serverid: %s", $bundleTask->id, $bundleTask->status, $bundleTask->serverId); } try { $dbServer = DBServer::LoadByID($bundleTask->serverId); } catch (\Scalr\Exception\ServerNotFoundException $e) { if (!$bundleTask->snapshotId && $bundleTask->bundleType != \SERVER_SNAPSHOT_CREATION_TYPE::GCE_WINDOWS) { $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::FAILED; $bundleTask->setDate('finished'); $bundleTask->failureReason = sprintf(_("Server '%s' was terminated during snapshot creation process"), $bundleTask->serverId); $bundleTask->Save(); return; } $this->getLogger()->warn("Could not load server: %s. %s says: %s", $bundleTask->serverId, get_class($e), $e->getMessage()); } catch (Exception $e) { $this->getLogger()->warn("Could not load server: %s. %s says: %s", $bundleTask->serverId, get_class($e), $e->getMessage()); } switch ($bundleTask->status) { case SERVER_SNAPSHOT_CREATION_STATUS::ESTABLISHING_COMMUNICATION: $conn = @fsockopen($dbServer->getSzrHost(), $dbServer->getPort(DBServer::PORT_CTRL), $errno, $errstr, 10); if ($conn) { $dbServer->SetProperty(SERVER_PROPERTIES::SZR_IMPORTING_OUT_CONNECTION, 1); $this->bundleTaskLog("Outbound connection successfully established. Awaiting user action: prebuild automation selection"); $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::AWAITING_USER_ACTION; $this->bundleTaskLog(sprintf(_("Bundle task status: %s"), $bundleTask->status)); $bundleTask->Save(); } else { $errstr = sprintf("Unable to establish outbound (Scalr -> Scalarizr) communication (%s:%s): %s.", $dbServer->getSzrHost(), $dbServer->getPort(DBServer::PORT_CTRL), $errstr); $errMsg = $dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_OUT_CONNECTION_ERROR); if (!$errMsg || $errstr != $errMsg) { $dbServer->SetProperty(SERVER_PROPERTIES::SZR_IMPORTING_OUT_CONNECTION_ERROR, $errstr); $this->bundleTaskLog("{$errstr} Will try again in a few minutes."); } } return false; case SERVER_SNAPSHOT_CREATION_STATUS::AWAITING_USER_ACTION: //nothing to do; return false; case SERVER_SNAPSHOT_CREATION_STATUS::STARING_SERVER: $bundleTask->setDate('started'); case SERVER_SNAPSHOT_CREATION_STATUS::PREPARING_ENV: case SERVER_SNAPSHOT_CREATION_STATUS::INTALLING_SOFTWARE: if (!PlatformFactory::NewPlatform($dbServer->platform)->GetServerID($dbServer)) { $this->bundleTaskLog(sprintf(_("Waiting for temporary server"))); return false; } $status = PlatformFactory::NewPlatform($dbServer->platform)->GetServerRealStatus($dbServer); if ($status->isPending()) { //Server is in pensing state $this->bundleTaskLog(sprintf(_("Server status: %s"), $status->getName())); $this->bundleTaskLog(sprintf(_("Waiting for running state."), $status->getName())); return false; } elseif ($status->isTerminated()) { $this->bundleTaskLog(sprintf(_("Server status: %s"), $status->getName())); $dbServer->status = SERVER_STATUS::TERMINATED; $dbServer->save(); $bundleTask->SnapshotCreationFailed("Server was terminated and no longer available in cloud."); return false; } break; } $this->getLogger()->info("Continue bundle task id:%d status:%s", $bundleTask->id, $bundleTask->status); switch ($bundleTask->status) { case SERVER_SNAPSHOT_CREATION_STATUS::STARING_SERVER: $ips = PlatformFactory::NewPlatform($dbServer->platform)->GetServerIPAddresses($dbServer); $dbServer->remoteIp = $ips['remoteIp']; $dbServer->localIp = $ips['localIp']; $dbServer->save(); $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::PREPARING_ENV; $bundleTask->save(); $this->bundleTaskLog(sprintf(_("Bundle task status: %s"), $bundleTask->status)); break; case SERVER_SNAPSHOT_CREATION_STATUS::PREPARING_ENV: $this->bundleTaskLog(sprintf(_("Initializing SSH2 session to the server"))); if ($dbServer->platform == SERVER_PLATFORMS::IDCF && !$dbServer->remoteIp) { try { $this->bundleTaskLog("Creating port forwarding rules to be able to connect to the server by SSH"); $environment = $dbServer->GetEnvironmentObject(); $cloudLocation = $dbServer->GetCloudLocation(); $platform = PlatformFactory::NewPlatform($dbServer->platform); $ccProps = $environment->keychain($dbServer->platform)->properties; $sharedIpId = $ccProps[CloudCredentialsProperty::CLOUDSTACK_SHARED_IP_ID . ".{$cloudLocation}"]; $sharedIp = $ccProps[CloudCredentialsProperty::CLOUDSTACK_SHARED_IP . ".{$cloudLocation}"]; $this->bundleTaskLog("Shared IP: {$sharedIp}"); $cs = $environment->cloudstack($dbServer->platform); // Create port forwarding rules for scalarizr $port = $ccProps[CloudCredentialsProperty::CLOUDSTACK_SZR_PORT_COUNTER . ".{$cloudLocation}.{$sharedIpId}"]; if (!$port) { $port1 = 30000; $port2 = 30001; $port3 = 30002; $port4 = 30003; } else { $port1 = $port + 1; $port2 = $port1 + 1; $port3 = $port2 + 1; $port4 = $port3 + 1; } $virtualmachineid = $dbServer->GetProperty(CLOUDSTACK_SERVER_PROPERTIES::SERVER_ID); $result2 = $cs->firewall->createPortForwardingRule(array('ipaddressid' => $sharedIpId, 'privateport' => 8014, 'protocol' => "udp", 'publicport' => $port1, 'virtualmachineid' => $virtualmachineid)); $result1 = $cs->firewall->createPortForwardingRule(array('ipaddressid' => $sharedIpId, 'privateport' => 8013, 'protocol' => "tcp", 'publicport' => $port1, 'virtualmachineid' => $virtualmachineid)); $result3 = $cs->firewall->createPortForwardingRule(array('ipaddressid' => $sharedIpId, 'privateport' => 8010, 'protocol' => "tcp", 'publicport' => $port3, 'virtualmachineid' => $virtualmachineid)); $result4 = $cs->firewall->createPortForwardingRule(array('ipaddressid' => $sharedIpId, 'privateport' => 8008, 'protocol' => "tcp", 'publicport' => $port2, 'virtualmachineid' => $virtualmachineid)); $result5 = $cs->firewall->createPortForwardingRule(array('ipaddressid' => $sharedIpId, 'privateport' => 22, 'protocol' => "tcp", 'publicport' => $port4, 'virtualmachineid' => $virtualmachineid)); $dbServer->SetProperties(array(SERVER_PROPERTIES::SZR_CTRL_PORT => $port1, SERVER_PROPERTIES::SZR_SNMP_PORT => $port1, SERVER_PROPERTIES::SZR_API_PORT => $port3, SERVER_PROPERTIES::SZR_UPDC_PORT => $port2, SERVER_PROPERTIES::CUSTOM_SSH_PORT => $port4)); $dbServer->remoteIp = $sharedIp; $dbServer->Save(); $ccProps->saveSettings([CloudCredentialsProperty::CLOUDSTACK_SZR_PORT_COUNTER . ".{$cloudLocation}.{$sharedIpId}" => $port4]); } catch (Exception $e) { $this->bundleTaskLog("Unable to create port-forwarding rules: {$e->getMessage()}"); } return false; } try { $ssh2Client = $dbServer->GetSsh2Client(); $ssh2Client->connect($dbServer->remoteIp, $dbServer->getPort(DBServer::PORT_SSH)); } catch (Exception $e) { $this->bundleTaskLog(sprintf(_("Scalr unable to establish SSH connection with server on %:%. Error: %s"), $dbServer->remoteIp, $dbServer->getPort(DBServer::PORT_SSH), $e->getMessage())); //TODO: Set status of bundle log to failed return false; } $this->bundleTaskLog(sprintf(_("Created SSH session. Username: %s"), $ssh2Client->getLogin())); //Prepare script $this->bundleTaskLog(sprintf(_("Uploading builder scripts..."))); $behaviors = $dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_BEHAVIOR); try { if ($dbServer->isOpenstack()) { $platform = SERVER_PLATFORMS::OPENSTACK; } else { $platform = $dbServer->platform; } $baseUrl = rtrim(\Scalr::config('scalr.endpoint.scheme') . "://" . \Scalr::config('scalr.endpoint.host'), '/'); $options = array('server-id' => $dbServer->serverId, 'role-name' => $bundleTask->roleName, 'crypto-key' => $dbServer->GetProperty(SERVER_PROPERTIES::SZR_KEY), 'platform' => $platform, 'queryenv-url' => $baseUrl . "/query-env", 'messaging-p2p.producer-url' => $baseUrl . "/messaging", 'behaviour' => trim(trim(str_replace("base", "", $behaviors), ",")), 'env-id' => $dbServer->envId, 'region' => $dbServer->GetCloudLocation(), 'scalr-id' => SCALR_ID); $command = 'scalarizr --import -y'; foreach ($options as $k => $v) { $command .= sprintf(' -o %s=%s', $k, $v); } if ($dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_MYSQL_SERVER_TYPE) == 'percona') { $recipes = 'mysql=percona'; } else { $recipes = ''; } $scalarizrBranch = $dbServer->GetProperty(SERVER_PROPERTIES::SZR_DEV_SCALARIZR_BRANCH); $scriptContents = @file_get_contents(APPPATH . "/templates/services/role_builder/chef_import.tpl"); /* %CHEF_SERVER_URL% %CHEF_VALIDATOR_NAME% %CHEF_VALIDATOR_KEY% %CHEF_ENVIRONMENT% %CHEF_ROLE_NAME% */ $chefServerId = $dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_CHEF_SERVER_ID); if ($chefServerId) { $chefServerInfo = $db->GetRow("SELECT * FROM services_chef_servers WHERE id=?", array($chefServerId)); $chefServerInfo['v_auth_key'] = \Scalr::getContainer()->crypto->decrypt($chefServerInfo['v_auth_key']); } $scriptContents = str_replace(array("%PLATFORM%", "%BEHAVIOURS%", "%SZR_IMPORT_STRING%", "%DEV%", "%SCALARIZR_BRANCH%", "%RECIPES%", "%BUILD_ONLY%", "%CHEF_SERVER_URL%", "%CHEF_VALIDATOR_NAME%", "%CHEF_VALIDATOR_KEY%", "%CHEF_ENVIRONMENT%", "%CHEF_ROLE%", "%CHEF_ROLE_NAME%", "%CHEF_NODE_NAME%", "\r\n"), array($platform, trim(str_replace("base", "", str_replace(",", " ", $behaviors))), $command, $scalarizrBranch ? '1' : '0', $scalarizrBranch, $recipes, '0', $chefServerInfo['url'], $chefServerInfo['v_username'], $chefServerInfo['v_auth_key'], $dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_CHEF_ENVIRONMENT), $dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_CHEF_ROLE_NAME), $dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_CHEF_ROLE_NAME), '', "\n"), $scriptContents); if (!$ssh2Client->sendFile('/tmp/scalr-builder.sh', $scriptContents, "w+", false)) { throw new Exception("Cannot upload script"); } /* $this->bundleTaskLog(sprintf(_("Uploading chef recipes..."))); if (!$ssh2Client->sendFile('/tmp/recipes.tar.gz', APPPATH . '/www/storage/chef/recipes.tar.gz')) { throw new Exception("Cannot upload chef recipes"); } */ } catch (Exception $e) { $this->bundleTaskLog(sprintf(_("Scripts upload failed: %s"), $e->getMessage())); //TODO: Set status of bundle log to failed return false; } $this->bundleTaskLog("Launching role builder routines on server"); $ssh2Client->exec("chmod 0777 /tmp/scalr-builder.sh"); // For CGE we need to use sudo if ($bundleTask->platform == SERVER_PLATFORMS::GCE || $bundleTask->osFamily == 'amazon') { $shell = $ssh2Client->getShell(); @stream_set_blocking($shell, true); @stream_set_timeout($shell, 5); @fwrite($shell, "sudo touch /var/log/role-builder-output.log 2>&1" . PHP_EOL); $output = @fgets($shell, 4096); $this->bundleTaskLog("Verbose 1: {$output}"); @fwrite($shell, "sudo chmod 0666 /var/log/role-builder-output.log 2>&1" . PHP_EOL); $output2 = @fgets($shell, 4096); $this->bundleTaskLog("Verbose 2: {$output2}"); @fwrite($shell, "sudo setsid /tmp/scalr-builder.sh > /var/log/role-builder-output.log 2>&1 &" . PHP_EOL); $output3 = @fgets($shell, 4096); $this->bundleTaskLog("Verbose 3: {$output3}"); sleep(5); $meta = stream_get_meta_data($shell); $this->bundleTaskLog(sprintf("Verbose (Meta): %s", json_encode($meta))); $i = 4; if ($meta['eof'] == false && $meta['unread_bytes'] != 0) { $output4 = @fread($shell, $meta['unread_bytes']); $this->bundleTaskLog("Verbose {$i}: {$output4}"); $meta = stream_get_meta_data($shell); $this->bundleTaskLog(sprintf("Verbose (Meta): %s", json_encode($meta))); } @fclose($shell); /* $r1 = $ssh2Client->exec("sudo touch /var/log/role-builder-output.log"); $this->bundleTaskLog("1: {$r1} ({$ssh2Client->stdErr})"); $r2 = $ssh2Client->exec("sudo chmod 0666 /var/log/role-builder-output.log"); $this->bundleTaskLog("2: {$r2} ({$ssh2Client->stdErr})"); $r3 = $ssh2Client->exec("sudo setsid /tmp/scalr-builder.sh > /var/log/role-builder-output.log 2>&1 &"); $this->bundleTaskLog("3: {$r3} ({$ssh2Client->stdErr})"); */ } else { $ssh2Client->exec("setsid /tmp/scalr-builder.sh > /var/log/role-builder-output.log 2>&1 &"); } $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::INTALLING_SOFTWARE; $bundleTask->save(); break; case SERVER_SNAPSHOT_CREATION_STATUS::INTALLING_SOFTWARE: try { $ssh2Client = $dbServer->GetSsh2Client(); $ssh2Client->connect($dbServer->remoteIp, $dbServer->getPort(DBServer::PORT_SSH)); } catch (Exception $e) { $this->bundleTaskLog(sprintf(_("Scalr unable to establish SSH connection with server on %:%. Error: %s"), $dbServer->remoteIp, $dbServer->getPort(DBServer::PORT_SSH), $e->getMessage())); //TODO: Set status of bundle log to failed return false; } $log = $ssh2Client->getFile('/var/log/role-builder-output.log'); $log_lines = explode("\r\n", $log); $last_msg = $dbServer->GetProperty(SERVER_PROPERTIES::SZR_IMPORTING_LAST_LOG_MESSAGE); while ($msg = trim(array_shift($log_lines))) { if (substr($msg, -1, 1) != ']') { continue; } if ($last_msg) { if ($msg != $last_msg) { continue; } elseif ($msg == $last_msg) { $last_msg = null; continue; } } if (stristr($msg, '[ Failed ]')) { $stepLog = $ssh2Client->getFile('/var/log/role-builder-step.log'); $this->bundleTaskLog(sprintf("role-builder-step.log: %s", $stepLog)); $bundleTask->SnapshotCreationFailed($msg); } else { $this->bundleTaskLog($msg); $dbServer->SetProperty(SERVER_PROPERTIES::SZR_IMPORTING_LAST_LOG_MESSAGE, $msg); } } //Read /var/log/role-builder-output.log break; case SERVER_SNAPSHOT_CREATION_STATUS::PENDING: try { $platformModule = PlatformFactory::NewPlatform($bundleTask->platform); $platformModule->CreateServerSnapshot($bundleTask); } catch (Exception $e) { $this->getLogger()->error($e->getMessage()); $bundleTask->SnapshotCreationFailed($e->getMessage()); } break; case SERVER_SNAPSHOT_CREATION_STATUS::PREPARING: $addedTime = strtotime($bundleTask->dateAdded); if ($addedTime + 3600 < time()) { $bundleTask->SnapshotCreationFailed("Server didn't send PrepareBundleResult message in time."); } break; case SERVER_SNAPSHOT_CREATION_STATUS::IN_PROGRESS: PlatformFactory::NewPlatform($bundleTask->platform)->CheckServerSnapshotStatus($bundleTask); break; case SERVER_SNAPSHOT_CREATION_STATUS::CREATING_ROLE: try { if ($bundleTask->object == BundleTask::BUNDLETASK_OBJECT_IMAGE) { if ($bundleTask->replaceType == SERVER_REPLACEMENT_TYPE::REPLACE_ALL) { $dbRole = $dbServer->GetFarmRoleObject()->GetRoleObject(); $dbRole->__getNewRoleObject()->setImage($bundleTask->platform, $bundleTask->cloudLocation, $bundleTask->snapshotId, $bundleTask->createdById, $bundleTask->createdByEmail); $this->bundleTaskLog(sprintf(_("Image replacement completed."))); } $this->bundleTaskLog(sprintf(_("Bundle task completed."))); $bundleTask->setDate('finished'); $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::SUCCESS; $bundleTask->Save(); } elseif ($bundleTask->object == BundleTask::BUNDLETASK_OBJECT_ROLE) { if ($bundleTask->replaceType == SERVER_REPLACEMENT_TYPE::REPLACE_ALL) { $saveOldRole = false; try { $dbRole = $dbServer->GetFarmRoleObject()->GetRoleObject(); if ($dbRole->name == $bundleTask->roleName && $dbRole->envId == $bundleTask->envId) { $saveOldRole = true; } } catch (Exception $e) { //NO OLD ROLE } if ($dbRole && $saveOldRole) { if ($dbServer) { $new_role_name = BundleTask::GenerateRoleName($dbServer->GetFarmRoleObject(), $dbServer); } else { $new_role_name = $bundleTask->roleName . "-" . rand(1000, 9999); } $dbRole->name = $new_role_name; $this->bundleTaskLog(sprintf(_("Old role '%s' (ID: %s) renamed to '%s'"), $bundleTask->roleName, $dbRole->id, $new_role_name)); $dbRole->save(); } } try { $DBRole = DBRole::createFromBundleTask($bundleTask); } catch (Exception $e) { $bundleTask->SnapshotCreationFailed("Role creation failed due to internal error ({$e->getMessage()}). Please try again."); return; } if ($bundleTask->replaceType == SERVER_REPLACEMENT_TYPE::NO_REPLACE) { $bundleTask->setDate('finished'); $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::SUCCESS; $this->bundleTaskLog(sprintf(_("Replacement type: %s. Bundle task status: %s"), SERVER_REPLACEMENT_TYPE::NO_REPLACE, SERVER_SNAPSHOT_CREATION_STATUS::SUCCESS)); } else { try { $this->bundleTaskLog(sprintf(_("Replacement type: %s"), $bundleTask->replaceType)); $r_farm_roles = array(); try { $DBFarm = DBFarm::LoadByID($bundleTask->farmId); } catch (Exception $e) { if (stristr($e->getMessage(), "not found in database")) { $bundleTask->SnapshotCreationFailed("Farm was removed before task was finished"); } return; } if ($bundleTask->replaceType == SERVER_REPLACEMENT_TYPE::REPLACE_FARM) { try { $r_farm_roles[] = $DBFarm->GetFarmRoleByRoleID($bundleTask->prototypeRoleId); } catch (Exception $e) { } } elseif ($bundleTask->replaceType == SERVER_REPLACEMENT_TYPE::REPLACE_ALL) { /* @var $user Entity\Account\User */ $user = Entity\Account\User::findPk($bundleTask->createdById); /* @var $env Entity\Account\Environment */ $env = Entity\Account\Environment::findPk($bundleTask->envId); /* @var $acl Acl */ $acl = Scalr::getContainer()->acl; $sql = "SELECT fr.id FROM farm_roles fr JOIN farms f ON f.id = fr.farmid WHERE fr.role_id=? AND f.env_id = ?"; $args = [$bundleTask->prototypeRoleId, $bundleTask->envId]; if (!$acl->isUserAllowedByEnvironment($user, $env, Acl::RESOURCE_FARMS, Acl::PERM_FARMS_UPDATE)) { $q = []; if ($acl->isUserAllowedByEnvironment($user, $env, Acl::RESOURCE_TEAM_FARMS, Acl::PERM_FARMS_UPDATE)) { $q[] = Entity\Farm::getUserTeamOwnershipSql($user->id); } if ($acl->isUserAllowedByEnvironment($user, $env, Acl::RESOURCE_OWN_FARMS, Acl::PERM_FARMS_UPDATE)) { $q[] = "f.created_by_id = ?"; $args[] = $user->getId(); } if (count($q)) { $sql .= ' AND (' . join(' OR ', $q) . ')'; } else { $sql .= ' AND 0'; // no permissions } } $farm_roles = $db->GetAll($sql, $args); foreach ($farm_roles as $farm_role) { try { $r_farm_roles[] = DBFarmRole::LoadByID($farm_role['id']); } catch (Exception $e) { } } } foreach ($r_farm_roles as $DBFarmRole) { if ($DBFarmRole->CloudLocation != $bundleTask->cloudLocation) { $this->bundleTaskLog(sprintf("Role '%s' (ID: %s), farm '%s' (ID: %s) using the same role " . "but in abother cloud location. Skiping it.", $DBFarmRole->GetRoleObject()->name, $DBFarmRole->ID, $DBFarmRole->GetFarmObject()->Name, $DBFarmRole->FarmID)); } else { $DBFarmRole->RoleID = $bundleTask->roleId; $DBFarmRole->Save(); } } $this->bundleTaskLog(sprintf(_("Replacement completed. Bundle task completed."))); try { if ($dbServer->status == SERVER_STATUS::IMPORTING) { $dbServer->Remove(); } elseif ($dbServer->status == SERVER_STATUS::TEMPORARY) { $this->bundleTaskLog("Terminating temporary server"); $dbServer->terminate(DBServer::TERMINATE_REASON_TEMPORARY_SERVER_ROLE_BUILDER); $this->bundleTaskLog("Termination request has been sent"); } } catch (Exception $e) { $this->bundleTaskLog("Warning: {$e->getMessage()}"); } $bundleTask->setDate('finished'); $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::SUCCESS; $bundleTask->Save(); } catch (Exception $e) { $this->getLogger()->error($e->getMessage()); $this->bundleTaskLog(sprintf(_("Server replacement failed: %s"), $e->getMessage())); $bundleTask->setDate('finished'); $bundleTask->status = SERVER_SNAPSHOT_CREATION_STATUS::SUCCESS; } } } if ($bundleTask->status == SERVER_SNAPSHOT_CREATION_STATUS::SUCCESS) { try { if ($dbServer->status == SERVER_STATUS::IMPORTING) { $dbServer->Remove(); } elseif ($dbServer->status == SERVER_STATUS::TEMPORARY) { $this->bundleTaskLog("Terminating temporary server"); $dbServer->terminate(DBServer::TERMINATE_REASON_TEMPORARY_SERVER_ROLE_BUILDER); $this->bundleTaskLog("Termination request has been sent"); } } catch (Exception $e) { $this->bundleTaskLog("Warning: {$e->getMessage()}"); } } $bundleTask->Save(); } catch (Exception $e) { $this->getLogger()->error($e->getMessage()); } break; } return $request; }
/** * {@inheritdoc} * @see ServerImportInterface::import() */ public function import($instanceId, $tags = []) { $instances = PlatformFactory::NewPlatform($this->farmRole->platform)->getOrphanedServers($this->farmRole->getFarm()->getEnvironment(), $this->farmRole->cloudLocation, [$instanceId]); if (count($instances) != 1) { throw new ValidationErrorException("Instance was not found"); } $this->orphaned = $instances[0]; $this->tags = $tags; $this->validate(); $farm = $this->farmRole->getFarm(); $server = $this->server = new Entity\Server(); try { $server->serverId = \Scalr::GenerateUID(false); // DBServer::Create, startWithLetter $server->platform = $this->farmRole->platform; $server->cloudLocation = $this->farmRole->cloudLocation; $server->accountId = $farm->accountId; $server->envId = $farm->envId; $server->farmId = $farm->id; $server->farmRoleId = $this->farmRole->id; $server->imageId = $this->orphaned->imageId; $server->status = Entity\Server::STATUS_RUNNING; $server->type = $this->orphaned->instanceType; $server->remoteIp = $this->orphaned->publicIp; $server->localIp = $this->orphaned->privateIp; $server->added = new DateTime(); $server->initialized = new DateTime(); // initialized is used in billing, so we set current time as start point $server->scalarized = 0; $server->setFreeFarmIndex(); $server->setFreeFarmRoleIndex(); $server->properties[Entity\Server::SZR_KEY] = \Scalr::GenerateRandomKey(40); $server->properties[Entity\Server::SZR_KEY_TYPE] = SZR_KEY_TYPE::ONE_TIME; $server->properties[Entity\Server::SZR_VESION] = ''; $server->properties[Entity\Server::LAUNCHED_BY_ID] = $this->user->id; $server->properties[Entity\Server::LAUNCHED_BY_EMAIL] = $this->user->email; $server->properties[Entity\Server::LAUNCH_REASON_ID] = DBServer::LAUNCH_REASON_IMPORT; $server->properties[Entity\Server::LAUNCH_REASON] = DBServer::getLaunchReason(DBServer::LAUNCH_REASON_IMPORT); $server->properties[Entity\Server::FARM_ROLE_ID] = $this->farmRole->id; $server->properties[Entity\Server::ROLE_ID] = $this->farmRole->roleId; $server->properties[Entity\Server::FARM_CREATED_BY_ID] = $farm->ownerId ?: $farm->settings[Entity\FarmSetting::CREATED_BY_ID]; $server->properties[Entity\Server::FARM_CREATED_BY_EMAIL] = $farm->ownerId ? Entity\Account\User::findPk($farm->ownerId)->email : $farm->settings[Entity\FarmSetting::CREATED_BY_EMAIL]; // projectId, ccId $projectId = $farm->settings[Entity\FarmSetting::PROJECT_ID]; $ccId = null; if (!empty($projectId)) { try { $projectEntity = ProjectEntity::findPk($projectId); if ($projectEntity instanceof ProjectEntity) { /* @var $projectEntity ProjectEntity */ $ccId = $projectEntity->ccId; } else { $projectId = null; } } catch (Exception $e) { $projectId = null; } } $server->properties[Entity\Server::FARM_PROJECT_ID] = $projectId; if (empty($ccId)) { $ccId = Entity\Account\Environment::findPk($farm->envId)->getProperty(Entity\Account\EnvironmentProperty::SETTING_CC_ID); } $server->properties[Entity\Server::ENV_CC_ID] = $ccId; if (!empty($server->getImage())) { $server->getImage()->update(['dtLastUsed' => new DateTime()]); } if (!empty($this->farmRole->getRole())) { $this->farmRole->getRole()->update(['lastUsed' => new DateTime()]); } $this->importServer(); $server->save(); $server->setTimeLog('ts_created'); $server->setTimeLog('ts_launched', time()); $history = $server->getHistory(); $history->markAsLaunched($server->properties[Entity\Server::LAUNCH_REASON], $server->properties[Entity\Server::LAUNCH_REASON_ID]); $history->update(['cloudServerId' => $this->orphaned->cloudServerId, 'scuCollecting' => 1]); $this->applyTags(); return $server; } catch (Exception $e) { if (!empty($server->serverId)) { // cleanup $server->deleteBy([['serverId' => $server->serverId]]); Entity\ServerProperty::deleteBy([['serverId' => $server->serverId]]); Entity\Server\History::deletePk($server->serverId); $this->db->Execute("DELETE FROM `servers_launch_timelog` WHERE server_id = ?", [$server->serverId]); } throw new ServerImportException(sprintf("Server create was failed with error: %s", $e->getMessage()), $e->getCode(), $e); } }
/** * {@inheritdoc} * @see AbstractEntity::save() */ public function save() { $this->changed = microtime(); $db = $this->db(); try { $db->BeginTrans(); if (empty($this->id)) { $this->ownerId = $this->changedById; $this->settings[FarmSetting::CREATED_BY_ID] = $this->ownerId; $this->settings[FarmSetting::CREATED_BY_EMAIL] = User::findPk($this->ownerId)->email; $this->added = new DateTime(); $this->status = FARM_STATUS::TERMINATED; if (empty($this->settings[FarmSetting::TIMEZONE])) { $this->settings[FarmSetting::TIMEZONE] = date_default_timezone_get(); } $this->settings[FarmSetting::CRYPTO_KEY] = \Scalr::GenerateRandomKey(40); /* @var $governance Governance */ $governance = Governance::findPk($this->envId, Governance::CATEGORY_GENERAL, Governance::GENERAL_LEASE); if (!empty($governance) && $governance->enabled) { $this->settings[FarmSetting::LEASE_STATUS] = 'Active'; } //TODO: unused field $this->region = Aws::REGION_US_EAST_1; } parent::save(); if (!empty($this->_settings)) { $this->_settings->save(); } if (isset($this->_teamsChanged)) { $this->saveTeams($this->_teams); $this->_teamsChanged = false; } $db->CommitTrans(); } catch (Exception $e) { $db->RollbackTrans(); throw $e; } }
public function FarmAddRole($Alias, $FarmID, $RoleID, $Platform, $CloudLocation, array $Configuration = array()) { try { $dbFarm = DBFarm::LoadByID($FarmID); if ($dbFarm->EnvID != $this->Environment->id) { throw new Exception("N"); } } catch (Exception $e) { throw new Exception(sprintf("Farm #%s not found", $FarmID)); } $this->user->getPermissions()->validate($dbFarm); $this->restrictFarmAccess($dbFarm, Acl::PERM_FARMS_UPDATE); $dbFarm->isLocked(true); $governance = new Scalr_Governance($this->Environment->id); $dbRole = DBRole::loadById($RoleID); if (!$dbRole->__getNewRoleObject()->hasAccessPermissions(User::findPk($this->user->getId()), Environment::findPk($this->Environment->id))) { throw new Exception(sprintf("Role #%s not found", $RoleID)); } if (!empty($envs = $dbRole->__getNewRoleObject()->getAllowedEnvironments())) { if (!in_array($this->Environment->id, $envs)) { throw new Exception(sprintf("Role #%s not found", $RoleID)); } } foreach ($dbRole->getBehaviors() as $behavior) { if ($behavior != ROLE_BEHAVIORS::BASE && $behavior != ROLE_BEHAVIORS::CHEF) { throw new Exception("Only base roles supported to be added to farm via API"); } } $config = array('scaling.enabled' => 0, 'scaling.min_instances' => 1, 'scaling.max_instances' => 1, 'scaling.polling_interval' => 2, 'system.timeouts.launch' => 9600, 'system.timeouts.reboot' => 9600); if (PlatformFactory::isOpenstack($Platform)) { //TODO: } if ($Platform == SERVER_PLATFORMS::EC2) { $config['aws.security_groups.list'] = json_encode(array('default', \Scalr::config('scalr.aws.security_group_name'))); $vpcId = $dbFarm->GetSetting(Entity\FarmSetting::EC2_VPC_ID); if ($vpcId) { if (!$Configuration['aws.vpc_subnet_id']) { throw new Exception("Farm configured to run inside VPC. 'aws.vpc_subnet_id' is required"); } $vpcRegion = $dbFarm->GetSetting(Entity\FarmSetting::EC2_VPC_REGION); if ($CloudLocation != $vpcRegion) { throw new Exception(sprintf("Farm configured to run inside VPC in %s region. Only roles in this region are allowed.", $vpcRegion)); } $vpcGovernance = $governance->getValue('ec2', 'aws.vpc'); $vpcGovernanceIds = $governance->getValue('ec2', 'aws.vpc', 'ids'); $subnets = json_decode($Configuration['aws.vpc_subnet_id'], true); if (count($subnets) == 0) { throw new Exception("Subnets list is empty or json is incorrect"); } $type = false; foreach ($subnets as $subnetId) { $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2); $info = $platform->listSubnets($this->Environment, $CloudLocation, $vpcId, true, $subnetId); if (substr($info['availability_zone'], 0, -1) != $vpcRegion) { throw new Exception(sprintf("Only subnets from %s region are allowed according to VPC settings", $vpcRegion)); } if ($vpcGovernance == 1) { // Check valid subnets if ($vpcGovernanceIds[$vpcId] && is_array($vpcGovernanceIds[$vpcId]) && !in_array($subnetId, $vpcGovernanceIds[$vpcId])) { throw new Exception(sprintf("Only %s subnet(s) allowed by governance settings", implode(', ', $vpcGovernanceIds[$vpcId]))); } // Check if subnets types if ($vpcGovernanceIds[$vpcId] == "outbound-only") { if ($info['type'] != 'private') { throw new Exception("Only private subnets allowed by governance settings"); } } if ($vpcGovernanceIds[$vpcId] == "full") { if ($info['type'] != 'public') { throw new Exception("Only public subnets allowed by governance settings"); } } } if (!$type) { $type = $info['type']; } else { if ($type != $info['type']) { throw new Exception("Mix of public and private subnets are not allowed. Please specify only public or only private subnets."); } } } } } if (PlatformFactory::isCloudstack($Platform)) { $config['cloudstack.security_groups.list'] = json_encode(array('default', \Scalr::config('scalr.aws.security_group_name'))); } if ($Platform == SERVER_PLATFORMS::GCE) { $config['gce.network'] = 'default'; $config['gce.on-host-maintenance'] = 'MIGRATE'; } if ($Configuration[Scalr_Role_Behavior_Chef::ROLE_CHEF_BOOTSTRAP] == 1 && !$Configuration[Scalr_Role_Behavior_Chef::ROLE_CHEF_ENVIRONMENT]) { $config[Scalr_Role_Behavior_Chef::ROLE_CHEF_ENVIRONMENT] = '_default'; } $config = array_merge($config, $Configuration); $this->validateFarmRoleConfiguration($config); if ($Platform == SERVER_PLATFORMS::GCE) { $config['gce.cloud-location'] = $CloudLocation; $config['gce.region'] = substr($CloudLocation, 0, -1); } $Alias = $this->stripValue($Alias); if (strlen($Alias) < 4) { throw new Exception("Role Alias should be longer than 4 characters"); } if (!preg_match("/^[A-Za-z0-9]+[A-Za-z0-9-]*[A-Za-z0-9]+\$/si", $Alias)) { throw new Exception("Alias should start and end with letter or number and contain only letters, numbers and dashes."); } if (!$this->Environment->isPlatformEnabled($Platform)) { throw new Exception("'{$Platform}' cloud is not configured in your environment"); } $images = $dbRole->__getNewRoleObject()->fetchImagesArray(); $locations = isset($images[$Platform]) ? array_keys($images[$Platform]) : []; if (!in_array($CloudLocation, $locations) && $Platform != SERVER_PLATFORMS::GCE) { throw new Exception(sprintf("Role '%s' doesn't have an image configured for cloud location '%s'", $dbRole->name, $CloudLocation)); } if ($Alias) { foreach ($dbFarm->GetFarmRoles() as $farmRole) { if ($farmRole->Alias == $Alias) { throw new Exception("Selected alias is already used by another role in selected farm"); } } } $dbFarmRole = $dbFarm->AddRole($dbRole, $Platform, $CloudLocation, 1); $dbFarmRole->Alias = $Alias ? $Alias : $dbRole->name; foreach ($config as $k => $v) { $dbFarmRole->SetSetting($k, trim($v), Entity\FarmRoleSetting::TYPE_CFG); } foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->onFarmSave($dbFarm, $dbFarmRole); } $dbFarmRole->Save(); $response = $this->CreateInitialResponse(); $response->FarmRoleID = $dbFarmRole->ID; return $response; }
/** * List farm roles and hosts list for each role * * Allowed args: role=(String Role Name) | behaviour=(app|www|mysql|base|memcached) * * @return DOMDocument */ protected function ListRoles() { $ResponseDOMDocument = $this->CreateResponse(); $RolesDOMNode = $ResponseDOMDocument->createElement('roles'); $ResponseDOMDocument->documentElement->appendChild($RolesDOMNode); $sql_query = "SELECT id FROM farm_roles WHERE farmid=?"; $sql_query_args = array($this->DBServer->farmId); // Filter by behaviour if ($this->GetArg("behaviour")) { $sql_query .= " AND role_id IN (SELECT role_id FROM role_behaviors WHERE behavior=?)"; array_push($sql_query_args, $this->GetArg("behaviour")); } // Filter by role if ($this->GetArg("role")) { $sql_query .= " AND role_id IN (SELECT id FROM roles WHERE name=?)"; array_push($sql_query_args, $this->GetArg("role")); } if ($this->GetArg("role-id")) { $sql_query .= " AND role_id = ?"; array_push($sql_query_args, $this->GetArg("role-id")); } if ($this->GetArg("farm-role-id")) { $sql_query .= " AND id = ?"; array_push($sql_query_args, $this->GetArg("farm-role-id")); } $farm_roles = $this->DB->GetAll($sql_query, $sql_query_args); foreach ($farm_roles as $farm_role) { $DBFarmRole = DBFarmRole::LoadByID($farm_role['id']); // Create role node $RoleDOMNode = $ResponseDOMDocument->createElement('role'); $RoleDOMNode->setAttribute('behaviour', implode(",", $DBFarmRole->GetRoleObject()->getBehaviors())); $RoleDOMNode->setAttribute('name', DBRole::loadById($DBFarmRole->RoleID)->name); $RoleDOMNode->setAttribute('alias', $DBFarmRole->Alias); $RoleDOMNode->setAttribute('id', $DBFarmRole->ID); $RoleDOMNode->setAttribute('role-id', $DBFarmRole->RoleID); $RoleDOMNode->setAttribute('scaling-min-instances', $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_MIN_INSTANCES)); $RoleDOMNode->setAttribute('scaling-max-instances', $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_MAX_INSTANCES)); $HostsDomNode = $ResponseDOMDocument->createElement('hosts'); $RoleDOMNode->appendChild($HostsDomNode); // List instances (hosts) $serversSql = "SELECT server_id FROM servers WHERE farm_roleid=?"; $serversArgs = array($farm_role['id'], SERVER_STATUS::RUNNING); if ($this->GetArg("showInitServers")) { $serversSql .= " AND status IN (?,?)"; $serversArgs[] = SERVER_STATUS::INIT; } else { $serversSql .= " AND status=?"; } $servers = $this->DB->GetAll($serversSql, $serversArgs); // Add hosts to response if (count($servers) > 0) { foreach ($servers as $server) { $DBServer = DBServer::LoadByID($server['server_id']); $serverProperties = $DBServer->GetAllProperties(); $HostDOMNode = $ResponseDOMDocument->createElement("host"); $HostDOMNode->setAttribute('scalr-server-id', $DBServer->serverId); $HostDOMNode->setAttribute('cloud-server-id', $DBServer->GetCloudServerID()); $HostDOMNode->setAttribute('internal-ip', $DBServer->localIp); $HostDOMNode->setAttribute('external-ip', $DBServer->remoteIp); $HostDOMNode->setAttribute('index', $DBServer->index); $HostDOMNode->setAttribute('status', $DBServer->status); $HostDOMNode->setAttribute('cloud-location', $DBServer->GetCloudLocation()); $HostDOMNode->setAttribute('cloud-location-zone', $DBServer->cloudLocationZone); $HostDOMNode->setAttribute('hostname', $serverProperties[Scalr_Role_Behavior::SERVER_BASE_HOSTNAME]); if (array_key_exists(SERVER_PROPERTIES::LAUNCHED_BY_EMAIL, $serverProperties)) { $launchedByEmail = $serverProperties[SERVER_PROPERTIES::LAUNCHED_BY_EMAIL]; } else { $launchedByEmail = Entity\Account\User::findPk($DBServer->GetFarmObject()->ownerId)->email; } $HostDOMNode->setAttribute('launched-by', $launchedByEmail); if (array_key_exists(SERVER_PROPERTIES::LAUNCH_REASON_ID, $serverProperties)) { $HostDOMNode->setAttribute('launch-reason-id', $serverProperties[SERVER_PROPERTIES::LAUNCH_REASON_ID]); } if ($DBFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::MONGODB)) { $HostDOMNode->setAttribute('replica-set-index', (int) $serverProperties[Scalr_Role_Behavior_MongoDB::SERVER_REPLICA_SET_INDEX]); $HostDOMNode->setAttribute('shard-index', (int) $serverProperties[Scalr_Role_Behavior_MongoDB::SERVER_SHARD_INDEX]); } if ($DBFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::MYSQL)) { if (array_key_exists(SERVER_PROPERTIES::DB_MYSQL_MASTER, $serverProperties)) { $isMySqlMaster = (int) $serverProperties[SERVER_PROPERTIES::DB_MYSQL_MASTER]; } else { $isMySqlMaster = 0; } $HostDOMNode->setAttribute('replication-master', $isMySqlMaster); } if ($DBFarmRole->GetRoleObject()->getDbMsrBehavior()) { if (array_key_exists(Scalr_Db_Msr::REPLICATION_MASTER, $serverProperties)) { $isMaster = (int) $serverProperties[Scalr_Db_Msr::REPLICATION_MASTER]; } else { $isMaster = 0; } $HostDOMNode->setAttribute('replication-master', $isMaster); } $HostsDomNode->appendChild($HostDOMNode); } } // Add role node to roles node $RolesDOMNode->appendChild($RoleDOMNode); } return $ResponseDOMDocument; }
/** * Generate data for ApiTest * * @param string $fixtures patch to fixtures directory * @param string $type api specifications type * @return array * @throws \Scalr\System\Config\Exception\YamlException */ public static function loadData($fixtures, $type) { // set config static::$testUserId = \Scalr::config('scalr.phpunit.apiv2.userid'); static::$user = User::findPk(static::$testUserId); static::$testEnvId = \Scalr::config('scalr.phpunit.apiv2.envid'); static::$env = Environment::findPk(static::$testEnvId); $data = []; foreach (new ApiFixtureIterator(new DirectoryIterator($fixtures), $type) as $fileInfo) { $class = __NAMESPACE__ . '\\' . ucfirst($fileInfo->getBasename('.yaml')); try { /* @var $object ApiFixture */ $object = new $class(Yaml::load($fileInfo->getPathname())->toArray(), $type); $object->prepareTestData(); $pathInfo = $object->preparePathInfo(); } catch (Exception $e) { $pathInfo = [array_merge([$class, $e, null, null, null], static::$defaultOperation)]; } $data = array_merge($data, $pathInfo); } return $data; }
/** * Authentication middleware */ public function authenticationMiddleware() { $bDebug = $this->request->headers('x-scalr-debug', 0) == 1; //If API is not enabled if (!$this->getContainer()->config('scalr.system.api.enabled')) { $this->halt(403, 'API is not enabled. See scalr.system.api.enabled'); } //Authentication $keyId = $this->request->headers('x-scalr-key-id'); $signature = $this->request->headers('x-scalr-signature'); //ISO-8601 formatted date $date = trim(preg_replace('/\\s+/', '', $this->request->headers('x-scalr-date'))); if (empty($keyId) || empty($signature)) { throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Unsigned request'); } elseif (empty($date) || ($time = strtotime($date)) === false) { throw new ApiErrorException(400, ErrorMessage::ERR_BAD_REQUEST, 'Missing or invalid X-Scalr-Date header'); } $sigparts = explode(' ', $signature, 2); if (empty($sigparts) || !in_array($sigparts[0], ['V1-HMAC-SHA256'])) { throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Invalid signature'); } $this->apiKey = ApiKeyEntity::findPk($keyId); if (!$this->apiKey instanceof ApiKeyEntity || !$this->apiKey->active) { throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Invalid API Key'); } if (abs(time() - $time) > 300) { throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Request is expired.' . ($bDebug ? ' Now is ' . gmdate('Y-m-d\\TH:i:s\\Z') : '')); } $now = new \DateTime('now'); if (empty($this->apiKey->lastUsed) || $now->getTimestamp() - $this->apiKey->lastUsed->getTimestamp() > 10) { $this->apiKey->lastUsed = $now; $this->apiKey->save(); } $qstr = $this->request->get(); $canonicalStr = ''; if (!empty($qstr)) { ksort($qstr); $canonicalStr = http_build_query($qstr, null, '&', PHP_QUERY_RFC3986); } $reqBody = $this->request->getBody(); $stringToSign = $this->request->getMethod() . "\n" . $date . "\n" . $this->request->getPath() . "\n" . $canonicalStr . "\n" . (empty($reqBody) ? '' : $reqBody); if ($bDebug) { $this->meta->stringToSign = $stringToSign; } switch ($sigparts[0]) { default: throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Invalid signature method. Please use "V1-HMAC-SHA256 [SIGNATURE]"'); break; case 'V1-HMAC-SHA256': $algo = strtolower(substr($sigparts[0], 8)); } $sig = base64_encode(hash_hmac($algo, $stringToSign, $this->apiKey->secretKey, 1)); if ($sig !== $sigparts[1]) { throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Signature does not match'); } $user = Entity\Account\User::findPk($this->apiKey->userId); /* @var $user Entity\Account\User */ if (!$user instanceof Entity\Account\User) { throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'User does not exist'); } if ($user->status != Entity\Account\User::STATUS_ACTIVE) { throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, 'Inactive user status'); } if (\Scalr::config('scalr.auth_mode') == 'ldap') { try { $ldap = \Scalr::getContainer()->ldap($user->getLdapUsername(), null); if (!$ldap->isValidUsername()) { if ($bDebug && $ldap->getConfig()->debug) { $this->meta->ldapDebug = $ldap->getLog(); } throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'User does not exist'); } $user->applyLdapGroups($ldap->getUserGroups()); } catch (LdapException $e) { if ($bDebug && $ldap instanceof LdapClient && $ldap->getConfig()->debug) { $this->meta->ldapDebug = $ldap->getLog(); } throw new \RuntimeException($e->getMessage()); } } $this->limiter->checkAccountRateLimit($this->apiKey->keyId); //Validates API version if ($this->settings[ApiApplication::SETTING_API_VERSION] != 1) { throw new ApiErrorException(400, ErrorMessage::ERR_BAD_REQUEST, 'Invalid API version'); } if ($this->request->getBody() !== '' && strtolower($this->request->getMediaType()) !== 'application/json') { throw new ApiErrorException(400, ErrorMessage::ERR_BAD_REQUEST, 'Invalid Content-Type'); } $this->setUser($user); $container = $this->getContainer(); //Releases auditloger to ensure it will be updated $container->release('auditlogger'); //Adjusts metadata to invoke audit loger $container->setShared('auditlogger.metadata', function ($cont) use($user) { return (object) ['user' => $user, 'envId' => null, 'remoteAddr' => $this->request->getIp(), 'ruid' => null, 'requestType' => AuditLogger::REQUEST_TYPE_API, 'systemTask' => null]; }); }
public function getFarm2($farmId) { $dbFarm = DBFarm::LoadByID($farmId); $this->user->getPermissions()->validate($dbFarm); $farmRoles = array(); $variables = new Scalr_Scripting_GlobalVariables($this->user->getAccountId(), $this->getEnvironmentId(), ScopeInterface::SCOPE_FARM); $farmRoleVariables = new Scalr_Scripting_GlobalVariables($this->user->getAccountId(), $this->getEnvironmentId(), ScopeInterface::SCOPE_FARMROLE); foreach ($dbFarm->GetFarmRoles() as $dbFarmRole) { $scripts = $this->db->GetAll("\n SELECT farm_role_scripts.*, scripts.name, scripts.os\n FROM farm_role_scripts\n LEFT JOIN scripts ON scripts.id = farm_role_scripts.scriptid\n WHERE farm_roleid=? AND issystem='1'\n ", array($dbFarmRole->ID)); $scriptsObject = array(); foreach ($scripts as $script) { if (!empty($script['scriptid']) && $script['script_type'] == Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_SCALR || !empty($script['script_path']) && $script['script_type'] == Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_LOCAL || !empty($script['params']) && $script['script_type'] == Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_CHEF) { $s = array('script_type' => $script['script_type'], 'script_id' => (int) $script['scriptid'], 'script' => $script['name'], 'os' => $script['os'], 'params' => unserialize($script['params']), 'target' => $script['target'], 'version' => (int) $script['version'], 'timeout' => $script['timeout'], 'isSync' => (int) $script['issync'], 'order_index' => $script['order_index'], 'event' => $script['event_name'], 'script_path' => $script['script_path'], 'run_as' => $script['run_as']); if ($script['target'] == Script::TARGET_BEHAVIORS || $script['target'] == Script::TARGET_ROLES || $script['target'] == Script::TARGET_FARMROLES) { switch ($script['target']) { case $script['target'] == Script::TARGET_ROLES: $varName = 'target_roles'; break; case $script['target'] == Script::TARGET_FARMROLES: $varName = 'target_farmroles'; break; case $script['target'] == Script::TARGET_BEHAVIORS: $varName = 'target_behaviors'; break; } $s[$varName] = array(); $r = $this->db->GetAll("SELECT `target` FROM farm_role_scripting_targets WHERE farm_role_script_id = ?", array($script['id'])); foreach ($r as $v) { array_push($s[$varName], $v['target']); } } $scriptsObject[] = $s; } } //Scripting params $scriptingParams = $this->db->Execute("\n SELECT * FROM farm_role_scripting_params\n WHERE farm_role_id = ? AND farm_role_script_id = '0'\n ", array($dbFarmRole->ID)); $sParams = array(); while ($p = $scriptingParams->FetchRow()) { $sParams[] = array('hash' => $p['hash'], 'role_script_id' => $p['role_script_id'], 'params' => unserialize($p['params'])); } $scalingManager = new Scalr_Scaling_Manager($dbFarmRole); $scaling = array(); foreach ($scalingManager->getFarmRoleMetrics() as $farmRoleMetric) { $scaling[$farmRoleMetric->metricId] = $farmRoleMetric->getSettings(); } $roleName = $dbFarmRole->GetRoleObject()->name; $storages = array('configs' => $dbFarmRole->getStorage()->getConfigs()); foreach ($dbFarmRole->getStorage()->getVolumes() as $configKey => $config) { $storages['devices'][$configKey] = array(); foreach ($config as $device) { $info = array('farmRoleId' => $device->farmRoleId, 'placement' => $device->placement, 'serverIndex' => $device->serverIndex, 'storageId' => $device->storageId, 'storageConfigId' => $device->storageConfigId, 'status' => $device->status); try { $server = DBServer::LoadByFarmRoleIDAndIndex($device->farmRoleId, $device->serverIndex); if ($server->status != SERVER_STATUS::TERMINATED) { $info['serverId'] = $server->serverId; $info['serverInstanceId'] = $server->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID); } } catch (Exception $e) { $this->response->debugException($e); } $storages['devices'][$configKey][] = $info; } } $image = $dbFarmRole->GetRoleObject()->__getNewRoleObject()->getImage($dbFarmRole->Platform, $dbFarmRole->CloudLocation); $securityGroups = $this->getInitialSecurityGroupsList($dbFarmRole); $farmRoles[] = array('farm_role_id' => $dbFarmRole->ID, 'alias' => $dbFarmRole->Alias ? $dbFarmRole->Alias : $dbFarmRole->GetRoleObject()->name, 'role_id' => $dbFarmRole->RoleID, 'platform' => $dbFarmRole->Platform, 'os' => $dbFarmRole->GetRoleObject()->getOs()->name, 'os_family' => $dbFarmRole->GetRoleObject()->getOs()->family, 'os_generation' => $dbFarmRole->GetRoleObject()->getOs()->generation, 'os_version' => $dbFarmRole->GetRoleObject()->getOs()->version, 'osId' => $dbFarmRole->GetRoleObject()->getOs()->id, 'generation' => $dbFarmRole->GetRoleObject()->generation, 'group' => $dbFarmRole->GetRoleObject()->getCategoryName(), 'cat_id' => $dbFarmRole->GetRoleObject()->catId, 'isScalarized' => $dbFarmRole->GetRoleObject()->isScalarized, 'name' => $roleName, 'behaviors' => implode(",", $dbFarmRole->GetRoleObject()->getBehaviors()), 'scripting' => $scriptsObject, 'scripting_params' => $sParams, 'settings' => $dbFarmRole->GetAllSettings(), 'cloud_location' => $dbFarmRole->CloudLocation, 'launch_index' => (int) $dbFarmRole->LaunchIndex, 'scaling' => $scaling, 'image' => $image->getImage(), 'storages' => $storages, 'variables' => $farmRoleVariables->getValues($dbFarmRole->GetRoleID(), $dbFarm->ID, $dbFarmRole->ID), 'running_servers' => $dbFarmRole->GetRunningInstancesCount(), 'suspended_servers' => $dbFarmRole->GetSuspendedInstancesCount(), 'security_groups' => $securityGroups, 'hourly_rate' => $this->getInstanceTypeHourlyRate($dbFarmRole->Platform, $dbFarmRole->CloudLocation, $dbFarmRole->getInstanceType(), $dbFarmRole->GetRoleObject()->getOs()->family)); } $vpc = array(); if ($dbFarm->GetSetting(Entity\FarmSetting::EC2_VPC_ID)) { $vpc = array('id' => $dbFarm->GetSetting(Entity\FarmSetting::EC2_VPC_ID), 'region' => $dbFarm->GetSetting(Entity\FarmSetting::EC2_VPC_REGION)); } /* @var $farm Entity\Farm */ $farm = Entity\Farm::findPk($dbFarm->ID); // or implement AccessPermissionsInterface in DBFarm $farmOwnerEditable = $this->request->hasPermissions($farm, Acl::PERM_FARMS_CHANGE_OWNERSHIP) || $dbFarm->ownerId == $this->user->getId(); $projectEditable = $this->user->isAccountOwner() || $this->request->hasPermissions($farm, Acl::PERM_FARMS_PROJECTS); $farmTeams = $farm->getTeams()->map(function ($team) { /* @var $ft Entity\Account\Team */ return $team->name; }); return array('farm' => array('name' => $dbFarm->Name, 'description' => $dbFarm->Comments, 'rolesLaunchOrder' => $dbFarm->RolesLaunchOrder, 'timezone' => $dbFarm->GetSetting(Entity\FarmSetting::TIMEZONE), 'variables' => $variables->getValues(0, $dbFarm->ID), 'vpc' => $vpc, 'status' => $dbFarm->Status, 'hash' => $dbFarm->Hash, 'owner' => $farmOwnerEditable ? $dbFarm->ownerId : ($dbFarm->ownerId ? Entity\Account\User::findPk($dbFarm->ownerId)->email : ''), 'ownerEditable' => $farmOwnerEditable, 'teamOwner' => $farmTeams, 'teamOwnerEditable' => $farmOwnerEditable, 'launchPermission' => $this->request->hasPermissions($farm, Acl::PERM_FARMS_LAUNCH_TERMINATE), 'projectEditable' => $projectEditable, Entity\FarmSetting::SZR_UPD_REPOSITORY => $dbFarm->GetSetting(Entity\FarmSetting::SZR_UPD_REPOSITORY), Entity\FarmSetting::SZR_UPD_SCHEDULE => $dbFarm->GetSetting(Entity\FarmSetting::SZR_UPD_SCHEDULE)), 'roles' => $farmRoles, 'lock' => $dbFarm->isLocked(false), 'changed' => $dbFarm->changedTime); }