/** * @functional */ public function testUser() { $userId = \Scalr::config('scalr.phpunit.userid'); $envId = \Scalr::config('scalr.phpunit.envid'); if (empty($userId) || empty($envId)) { $this->markTestSkipped("This test requires valid database connection so it's considered to be functional."); } /* @var $user User */ $user = User::findOne([['id' => $userId]]); $this->assertInstanceOf('Scalr\\Model\\Entity\\Account\\User', $user); $email = $user->getSetting(UserSetting::NAME_GRAVATAR_EMAIL); $this->assertNotEmpty($email); $environment = Environment::findPk($envId); $this->assertInstanceOf('Scalr\\Model\\Entity\\Account\\Environment', $environment); $entityIterator = User::result(User::RESULT_ENTITY_ITERATOR)->find(null, null, null, 10); $this->assertInstanceOf('Scalr\\Model\\Collections\\EntityIterator', $entityIterator); $this->assertNotEmpty($entityIterator->count()); $this->assertNotEmpty($entityIterator->getArrayCopy()); foreach ($entityIterator->filterByType(User::TYPE_ACCOUNT_OWNER) as $item) { $this->assertEquals(User::TYPE_ACCOUNT_OWNER, $item->type); } foreach (User::result(User::RESULT_ENTITY_ITERATOR)->findByType(User::TYPE_SCALR_ADMIN) as $item) { $this->assertEquals(User::TYPE_SCALR_ADMIN, $item->type); } $arrayCollection = User::result(User::RESULT_ENTITY_COLLECTION)->find(null, null, null, 10); $this->assertInstanceOf('Scalr\\Model\\Collections\\ArrayCollection', $arrayCollection); $this->assertNotEmpty($arrayCollection->count()); $this->assertNotEmpty($arrayCollection->getArrayCopy()); $rs = User::result(User::RESULT_RAW)->find(null, null, null, 10); $this->assertInstanceOf('ADORecordSet', $rs); foreach ($rs as $item) { $this->assertNotEmpty($item); $this->assertInternalType('array', $item); } }
/** * 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; }
/** * Environment level authentication middleware */ public function environmentAuthenticationMiddleware() { if (empty($this->settings[self::SETTING_SCALR_ENVIRONMENT]) || $this->settings[self::SETTING_SCALR_ENVIRONMENT] <= 0) { throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Environment must be specified"); } $envId = $this->settings[self::SETTING_SCALR_ENVIRONMENT]; $environment = Entity\Account\Environment::findPk($envId); if (!$environment instanceof Entity\Account\Environment) { throw new ApiErrorException(403, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Invalid environment"); } $user = $this->getUser(); if (!$user instanceof Entity\Account\User) { throw new \Exception("User had to be set by the previous middleware, but he weren't"); } if (!$user->hasAccessToEnvironment($environment->id)) { throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "You don't have access to the environment."); } $this->setEnvironment($environment); //Sets Environment to Audit Logger $this->getContainer()->auditlogger->setEnvironmentId($environment->id); }
/** * 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))); }
/** * Gets Environment entity * * @param int $envId environment identifier * @return Environment */ public function getEnvironmentEntity($envId) { /* @var $env Environment */ $env = Environment::findPk($envId); static::toDelete(Environment::class, [$envId], ['accountId' => $env->accountId]); return $env; }
/** * 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(); }
/** * {@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; }
/** * Return Environment entity * * @return Environment|null */ public function getEnvironment() { if (!empty($this->envId) && empty($this->_environment)) { $this->_environment = Environment::findPk($this->envId); } return $this->_environment; }
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; }
/** * Add Project entities for test * * @param string $name Project data name */ protected function prepareProjects($name) { $ccId = Environment::findPk(static::$env->id)->getProperty(Account\EnvironmentProperty::SETTING_CC_ID); $this->prepareData($name); foreach ($this->sets[$name] as &$projectData) { $projectData['envId'] = self::$env->id; $projectData['accountId'] = self::$user->getAccountId(); $projectData['createdById'] = self::$user->id; $projectData['createdByEmail'] = self::$user->email; $projectData['ccId'] = $ccId; $properties = []; if (isset($projectData['properties'])) { $properties = $projectData['properties']; unset($projectData['properties']); } /* @var $project ProjectEntity */ $project = ApiTest::createEntity(new ProjectEntity(), $projectData); $projectData['id'] = $project->projectId; $project->setCostCenter(Scalr::getContainer()->analytics->ccs->get($projectData['ccId'])); if (!empty($properties)) { if (isset($projectData['billingCode'])) { $project->saveProperty(ProjectPropertyEntity::NAME_BILLING_CODE, $projectData['billingCode']); ApiTest::toDelete(ProjectPropertyEntity::class, [$project->projectId, $project->getProperty(ProjectPropertyEntity::NAME_BILLING_CODE)]); } if (isset($projectData['leadEmail'])) { $project->saveProperty(ProjectPropertyEntity::NAME_LEAD_EMAIL, $projectData['leadEmail']); ApiTest::toDelete(ProjectPropertyEntity::class, [$project->projectId, $project->getProperty(ProjectPropertyEntity::NAME_LEAD_EMAIL)]); } if (isset($projectData['description'])) { $project->saveProperty(ProjectPropertyEntity::NAME_DESCRIPTION, $projectData['description']); ApiTest::toDelete(ProjectPropertyEntity::class, [$project->projectId, $project->getProperty(ProjectPropertyEntity::NAME_DESCRIPTION)]); } } $project->save(); } }
/** * {@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); } }
/** * 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; }
/** * Get current environment as Entity * * @return Entity\Account\Environment Current environment */ public function getEnvironmentEntity() { if (empty($this->_environment) && !empty($this->environment)) { $this->_environment = Entity\Account\Environment::findPk($this->environment->id); } return $this->_environment; }