public function getDeployMessage()
 {
     $dbServer = DBServer::LoadByID($this->serverId);
     $application = Scalr_Dm_Application::init()->loadById($this->applicationId);
     $source = $application->getSource();
     $msgSource = new stdClass();
     $msgSource->url = $source->url;
     $msgSource->type = $source->type;
     switch ($source->authType) {
         case Scalr_Dm_Source::AUTHTYPE_PASSWORD:
             $msgSource->login = $source->getAuthInfo()->login;
             $msgSource->password = $source->getAuthInfo()->password;
             break;
         case Scalr_Dm_Source::AUTHTYPE_CERT:
             $msgSource->sshPrivateKey = $source->getAuthInfo()->sshPrivateKey;
             break;
     }
     $params['remote_path'] = $this->remotePath;
     // Prepare keys array and array with values for replacement in script
     $keys = array_keys($params);
     $f = create_function('$item', 'return "%".$item."%";');
     $keys = array_map($f, $keys);
     $values = array_values($params);
     // Generate script contents
     $preDeployScriptContents = str_replace($keys, $values, $application->getPreDeployScript());
     $preDeployScriptContents = str_replace('\\%', "%", $preDeployScriptContents);
     $postDeployScriptContents = str_replace($keys, $values, $application->getPostDeployScript());
     $postDeployScriptContents = str_replace('\\%', "%", $postDeployScriptContents);
     return new Scalr_Messaging_Msg_Deploy($this->id, $this->remotePath, $msgSource, $preDeployScriptContents, $postDeployScriptContents);
 }
Beispiel #2
0
 public function xRemoveApplicationsAction()
 {
     $this->request->defineParams(array('applicationId' => array('type' => 'int')));
     $application = Scalr_Dm_Application::init()->loadById($this->getParam('applicationId'));
     $this->user->getPermissions()->validate($application);
     $application->delete();
     $this->response->success();
 }
 public function DmApplicationCreate($Name, $SourceID, $PreDeployScript = null, $PostDeployScript = null)
 {
     $this->restrictAccess(Acl::RESOURCE_DEPLOYMENTS_APPLICATIONS);
     $application = Scalr_Model::init(Scalr_Model::DM_APPLICATION);
     $application->envId = $this->Environment->id;
     if (Scalr_Dm_Application::getIdByNameAndSource($Name, $SourceID)) {
         throw new Exception("Application already exists in database");
     }
     $application->name = $Name;
     $application->sourceId = $SourceID;
     $application->setPreDeployScript($PreDeployScript);
     $application->setPostDeployScript($PostDeployScript);
     $application->save();
     $response = $this->CreateInitialResponse();
     $response->ApplicationID = $application->id;
     return $response;
 }
Beispiel #4
0
 public function extendMessage(Scalr_Messaging_Msg $message, DBServer $dbServer)
 {
     if (in_array(ROLE_BEHAVIORS::BASE, $message->handlers)) {
         return $message;
     }
     if ($dbServer->farmRoleId) {
         $dbFarmRole = DBFarmRole::LoadByID($dbServer->farmRoleId);
     }
     switch (get_class($message)) {
         case "Scalr_Messaging_Msg_BeforeHostTerminate":
             //Storage
             try {
                 if ($dbFarmRole) {
                     $storage = new FarmRoleStorage($dbFarmRole);
                     $volumes = $storage->getVolumesConfigs($dbServer, false);
                     if (!empty($volumes)) {
                         $message->volumes = $volumes;
                     }
                 }
             } catch (Exception $e) {
                 $this->logger->error(new FarmLogMessage($dbServer->farmId, "Cannot init storage: {$e->getMessage()}"));
             }
             break;
         case "Scalr_Messaging_Msg_HostInit":
             $configuration = $this->getBaseConfiguration($dbServer, true, true);
             $message->base = $configuration->base;
             break;
         case "Scalr_Messaging_Msg_HostInitResponse":
             //Deployments
             try {
                 if ($dbFarmRole) {
                     $appId = $dbFarmRole->GetSetting(self::ROLE_DM_APPLICATION_ID);
                     if ($appId) {
                         $application = Scalr_Dm_Application::init()->loadById($appId);
                         $deploymentTask = Scalr_Dm_DeploymentTask::init();
                         $deploymentTask->create($dbServer->farmRoleId, $appId, $dbServer->serverId, Scalr_Dm_DeploymentTask::TYPE_AUTO, $dbFarmRole->GetSetting(self::ROLE_DM_REMOTE_PATH), $dbServer->envId, Scalr_Dm_DeploymentTask::STATUS_DEPLOYING);
                         $message->deploy = $deploymentTask->getDeployMessageProperties();
                     }
                 }
             } catch (Exception $e) {
                 $this->logger->error(new FarmLogMessage($dbServer->farmId, "Cannot init deployment: {$e->getMessage()}"));
             }
             $configuration = $this->getBaseConfiguration($dbServer, true);
             if ($configuration->volumes) {
                 $message->volumes = $configuration->volumes;
             }
             $message->base = $configuration->base;
             break;
     }
     $message->handlers[] = ROLE_BEHAVIORS::BASE;
     return $message;
 }
Beispiel #5
0
 public function extendMessage(Scalr_Messaging_Msg $message, DBServer $dbServer)
 {
     if (in_array(ROLE_BEHAVIORS::BASE, $message->handlers)) {
         return $message;
     }
     if ($dbServer->farmRoleId) {
         $dbFarmRole = DBFarmRole::LoadByID($dbServer->farmRoleId);
     }
     switch (get_class($message)) {
         case "Scalr_Messaging_Msg_BeforeHostTerminate":
             //Storage
             try {
                 if ($dbFarmRole) {
                     $storage = new FarmRoleStorage($dbFarmRole);
                     $volumes = $storage->getVolumesConfigs($dbServer->index);
                     if (!empty($volumes)) {
                         $message->volumes = $volumes;
                     }
                 }
             } catch (Exception $e) {
                 $this->logger->error(new FarmLogMessage($dbServer->farmId, "Cannot init storage: {$e->getMessage()}"));
             }
             break;
         case "Scalr_Messaging_Msg_HostInitResponse":
             //Deployments
             try {
                 if ($dbFarmRole) {
                     $appId = $dbServer->GetFarmRoleObject()->GetSetting(self::ROLE_DM_APPLICATION_ID);
                     if (!$message->deploy && $appId) {
                         $application = Scalr_Dm_Application::init()->loadById($appId);
                         $deploymentTask = Scalr_Dm_DeploymentTask::init();
                         $deploymentTask->create($dbServer->farmRoleId, $appId, $dbServer->serverId, Scalr_Dm_DeploymentTask::TYPE_AUTO, $dbFarmRole->GetSetting(self::ROLE_DM_REMOTE_PATH), $dbServer->envId, Scalr_Dm_DeploymentTask::STATUS_DEPLOYING);
                         $message->deploy = $deploymentTask->getDeployMessageProperties();
                     }
                 }
             } catch (Exception $e) {
                 $this->logger->error(new FarmLogMessage($dbServer->farmId, "Cannot init deployment: {$e->getMessage()}"));
             }
             //Storage
             try {
                 if ($dbFarmRole) {
                     $storage = new FarmRoleStorage($dbFarmRole);
                     $volumes = $storage->getVolumesConfigs($dbServer->index);
                     if (!empty($volumes)) {
                         $message->volumes = $volumes;
                     }
                 }
             } catch (Exception $e) {
                 $this->logger->error(new FarmLogMessage($dbServer->farmId, "Cannot init storage: {$e->getMessage()}"));
             }
             // Base
             try {
                 if ($dbFarmRole) {
                     $scriptingLogTimeout = $dbFarmRole->GetSetting(self::ROLE_BASE_KEEP_SCRIPTING_LOGS_TIME);
                     if (!$scriptingLogTimeout) {
                         $scriptingLogTimeout = 3600;
                     }
                     $message->base = new stdClass();
                     $message->base->keepScriptingLogsTime = $scriptingLogTimeout;
                     $hostNameFormat = $dbFarmRole->GetSetting(self::ROLE_BASE_HOSTNAME_FORMAT);
                     $message->base->hostname = !empty($hostNameFormat) ? $dbServer->applyGlobalVarsToValue($hostNameFormat) : '';
                 }
                 //keep_scripting_logs_time
             } catch (Exception $e) {
             }
             break;
     }
     $message->handlers[] = ROLE_BEHAVIORS::BASE;
     return $message;
 }
Beispiel #6
0
 /**
  *
  * @param array $farmSettings
  * @param array $roles
  * @return bool
  */
 private function isFarmConfigurationValid($farmId, $farmSettings, array $roles = array())
 {
     $this->errors = array('error_count' => 0);
     $farmVariables = new Scalr_Scripting_GlobalVariables($this->user->getAccountId(), $this->getEnvironmentId(), Scalr_Scripting_GlobalVariables::SCOPE_FARM);
     $farmRoleVariables = new Scalr_Scripting_GlobalVariables($this->user->getAccountId(), $this->getEnvironmentId(), Scalr_Scripting_GlobalVariables::SCOPE_FARMROLE);
     $name = $this->request->stripValue($farmSettings['name']);
     if (empty($name)) {
         $this->setBuildError('name', 'Farm name is invalid');
     }
     if ($farmSettings['variables']) {
         $result = $farmVariables->validateValues(is_array($farmSettings['variables']) ? $farmSettings['variables'] : [], 0, $farmId);
         if ($result !== TRUE) {
             $this->setBuildError('variables', $result);
         }
     }
     if (is_numeric($farmSettings['owner'])) {
         try {
             $u = (new Scalr_Account_User())->loadById($farmSettings['owner']);
             if ($u->getAccountId() != $this->user->getAccountId()) {
                 throw new Exception('User not found');
             }
         } catch (Exception $e) {
             $this->setBuildError('owner', $e->getMessage());
         }
     }
     if (is_numeric($farmSettings['teamOwner']) && $farmSettings['teamOwner'] > 0) {
         if ($this->user->canManageAcl()) {
             $teams = $this->db->getAll('SELECT id, name FROM account_teams WHERE account_id = ?', array($this->user->getAccountId()));
         } else {
             $teams = $this->user->getTeams();
         }
         if (!in_array($farmSettings['teamOwner'], array_map(function ($t) {
             return $t['id'];
         }, $teams))) {
             if ($this->db->GetOne('SELECT team_id FROM farms WHERE id = ?', [$farmId]) != $farmSettings['teamOwner']) {
                 $this->setBuildError('teamOwner', 'Team not found');
             }
         }
     }
     if (!empty($roles)) {
         $hasVpcRouter = false;
         $vpcRouterRequired = false;
         foreach ($roles as $role) {
             $dbRole = DBRole::loadById($role['role_id']);
             try {
                 $dbRole->__getNewRoleObject()->getImage($role['platform'], $role['cloud_location']);
             } catch (Exception $e) {
                 $this->setBuildError($dbRole->name, sprintf("Role '%s' is not available in %s on %s", $dbRole->name, $role['platform'], $role['cloud_location']));
             }
             if ($role['alias']) {
                 if (!preg_match("/^[A-Za-z0-9]+[A-Za-z0-9-]*[A-Za-z0-9]+\$/si", $role['alias'])) {
                     $this->setBuildError('alias', sprintf(_("Alias for role '%s' should start and end with letter or number and contain only letters, numbers and dashes."), $dbRole->name, $role['platform'], $role['cloud_location']), $role['farm_role_id']);
                 }
             }
             // Validate deployments
             $appId = $role[Scalr_Role_Behavior::ROLE_DM_APPLICATION_ID];
             if ($appId) {
                 $application = Scalr_Dm_Application::init()->loadById($appId);
                 $this->user->getPermissions()->validate($application);
                 if (!$role[Scalr_Role_Behavior::ROLE_DM_REMOTE_PATH]) {
                     $this->setBuildError(Scalr_Role_Behavior::ROLE_DM_REMOTE_PATH, sprintf("Remote path required for deployment on role '%s'", $dbRole->name), $role['farm_role_id']);
                 }
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER)) {
                 $hasVpcRouter = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) {
                 $role['settings'][DBFarmRole::SETTING_SCALING_MAX_INSTANCES] = $role['settings'][DBFarmRole::SETTING_SCALING_MIN_INSTANCES];
                 $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] = (int) $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO];
                 if ($role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] < 1 || $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] > 100) {
                     $this->setBuildError(Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO, sprintf("Nodes ratio for RabbitMq role '%s' should be between 1 and 100", $dbRole->name), $role['farm_role_id']);
                 }
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MONGODB)) {
                 if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_ENGINE] == 'ebs') {
                     if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] < 10 || $role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] > 1000) {
                         $this->setBuildError(Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE, sprintf("EBS size for mongoDB role should be between 10 and 1000 GB", $dbRole->name), $role['farm_role_id']);
                     }
                 }
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::NGINX)) {
                 $proxies = (array) @json_decode($role['settings'][Scalr_Role_Behavior_Nginx::ROLE_PROXIES], true);
                 foreach ($proxies as $proxyIndex => $proxy) {
                     if ($proxy['ssl'] == 1) {
                         if (empty($proxy['ssl_certificate_id'])) {
                             $this->setBuildError(Scalr_Role_Behavior_Nginx::ROLE_PROXIES, ['message' => 'SSL certificate is required', 'invalidIndex' => $proxyIndex], $role['farm_role_id']);
                             break;
                         }
                         if ($proxy['port'] == $proxy['ssl_port']) {
                             $this->setBuildError(Scalr_Role_Behavior_Nginx::ROLE_PROXIES, ['message' => 'HTTP and HTTPS ports cannot be the same', 'invalidIndex' => $proxyIndex], $role['farm_role_id']);
                         }
                     }
                     if (count($proxy['backends']) > 0) {
                         foreach ($proxy['backends'] as $backend) {
                             if (empty($backend['farm_role_id']) && empty($backend['farm_role_alias']) && empty($backend['host'])) {
                                 $this->setBuildError(Scalr_Role_Behavior_Nginx::ROLE_PROXIES, ['message' => 'Destination is required', 'invalidIndex' => $proxyIndex], $role['farm_role_id']);
                                 break;
                             }
                         }
                     }
                 }
             }
             /* Validate scaling */
             $minCount = (int) $role['settings'][DBFarmRole::SETTING_SCALING_MIN_INSTANCES];
             if (!$minCount && $minCount != 0) {
                 $minCount = 1;
             }
             if ($minCount < 0 || $minCount > 400) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_MIN_INSTANCES, sprintf(_("Min instances for '%s' must be a number between 0 and 400"), $dbRole->name), $role['farm_role_id']);
             }
             $maxCount = (int) $role['settings'][DBFarmRole::SETTING_SCALING_MAX_INSTANCES];
             if (!$maxCount) {
                 $maxCount = 1;
             }
             if ($maxCount < 1 || $maxCount > 400) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_MAX_INSTANCES, sprintf(_("Max instances for '%s' must be a number between 1 and 400"), $dbRole->name), $role['farm_role_id']);
             }
             if ($maxCount < $minCount) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_MAX_INSTANCES, sprintf(_("Max instances should be greater or equal than Min instances for role '%s'"), $dbRole->name), $role['farm_role_id']);
             }
             if (isset($role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL]) && $role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL] > 0) {
                 $polling_interval = (int) $role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL];
             } else {
                 $polling_interval = 2;
             }
             if ($polling_interval < 1 || $polling_interval > 50) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_POLLING_INTERVAL, sprintf(_("Polling interval for role '%s' must be a number between 1 and 50"), $dbRole->name), $role['farm_role_id']);
             }
             /** Validate platform specified settings **/
             switch ($role['platform']) {
                 case SERVER_PLATFORMS::EC2:
                     if ($role['settings'][DBFarmRole::SETTING_AWS_TAGS_LIST]) {
                         $reservedBaseCustomTags = ['scalr-meta', 'Name'];
                         $baseCustomTags = @explode("\n", $role['settings'][DBFarmRole::SETTING_AWS_TAGS_LIST]);
                         foreach ((array) $baseCustomTags as $tag) {
                             $tag = trim($tag);
                             $tagChunks = explode("=", $tag);
                             if (in_array(trim($tagChunks[0]), $reservedBaseCustomTags)) {
                                 $this->setBuildError(DBFarmRole::SETTING_AWS_TAGS_LIST, "Avoid using Scalr-reserved tag names.", $role['farm_role_id']);
                             }
                         }
                     }
                     if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MYSQL)) {
                         if ($role['settings'][DBFarmRole::SETTING_MYSQL_DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EBS) {
                             if ($dbRole->generation != 2) {
                                 if ($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == "" || $role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == "x-scalr-diff" || stristr($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE], 'x-scalr-custom')) {
                                     $this->setBuildError(DBFarmRole::SETTING_AWS_AVAIL_ZONE, sprintf(_("Requirement for EBS MySQL data storage is specific 'Placement' parameter for role '%s'"), $dbRole->name), $role['farm_role_id']);
                                 }
                             }
                         }
                     }
                     if ($dbRole->getDbMsrBehavior()) {
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EPH) {
                             if (!$role['settings'][Scalr_Db_Msr::DATA_STORAGE_EPH_DISK] && !$role['settings'][Scalr_Db_Msr::DATA_STORAGE_EPH_DISKS]) {
                                 $this->setBuildError(Scalr_Db_Msr::DATA_STORAGE_EPH_DISK, sprintf(_("Ephemeral disk settings is required for role '%s'"), $dbRole->name), $role['farm_role_id']);
                             }
                         }
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::LVM) {
                             if (!$role['settings'][Scalr_Role_DbMsrBehavior::ROLE_DATA_STORAGE_LVM_VOLUMES]) {
                                 $this->setBuildError(Scalr_Role_DbMsrBehavior::ROLE_DATA_STORAGE_LVM_VOLUMES, sprintf(_("LVM storage settings is required for role '%s'"), $dbRole->name), $role['farm_role_id']);
                             }
                         }
                     }
                     if ($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == 'x-scalr-custom=') {
                         $this->setBuildError(DBFarmRole::SETTING_AWS_AVAIL_ZONE, sprintf(_("Availability zone for role \"%s\" should be selected"), $dbRole->name), $role['farm_role_id']);
                     }
                     if ($farmSettings['vpc_id']) {
                         $sgs = @json_decode($role['settings'][DBFarmRole::SETTING_AWS_SECURITY_GROUPS_LIST]);
                         if (!$dbRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER) && empty($sgs) && !$role['settings'][DBFarmRole::SETTING_AWS_SG_LIST] && !$role['settings']['aws.security_group']) {
                             $this->setBuildError(DBFarmRole::SETTING_AWS_SECURITY_GROUPS_LIST, 'Security group(s) should be selected', $role['farm_role_id']);
                         }
                         $subnets = @json_decode($role['settings'][DBFarmRole::SETTING_AWS_VPC_SUBNET_ID]);
                         if (empty($subnets)) {
                             $this->setBuildError(DBFarmRole::SETTING_AWS_VPC_SUBNET_ID, 'VPC Subnet(s) should be selected', $role['farm_role_id']);
                         }
                         if (\Scalr::config('scalr.instances_connection_policy') != 'local' && !$role['settings'][Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID] && !$vpcRouterRequired) {
                             try {
                                 $subnets = @json_decode($role['settings'][DBFarmRole::SETTING_AWS_VPC_SUBNET_ID]);
                                 if ($subnets[0]) {
                                     $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2);
                                     $info = $platform->listSubnets($this->getEnvironment(), $role['cloud_location'], $farmSettings['vpc_id'], true, $subnets[0]);
                                     if ($info && $info['type'] == 'private') {
                                         $vpcRouterRequired = $role['farm_role_id'];
                                     }
                                 }
                             } catch (Exception $e) {
                             }
                         }
                     }
                     break;
                 case SERVER_PLATFORMS::CLOUDSTACK:
                     if (!$role['settings'][DBFarmRole::SETTING_CLOUDSTACK_SERVICE_OFFERING_ID]) {
                         $this->setBuildError(DBFarmRole::SETTING_CLOUDSTACK_SERVICE_OFFERING_ID, sprintf(_("Service offering for '%s' cloudstack role should be selected on 'Cloudstack settings' tab"), $dbRole->name), $role['farm_role_id']);
                     }
                     break;
                 case SERVER_PLATFORMS::RACKSPACE:
                     if (!$role['settings'][DBFarmRole::SETTING_RS_FLAVOR_ID]) {
                         $this->setBuildError(DBFarmRole::SETTING_CLOUDSTACK_SERVICE_OFFERING_ID, sprintf(_("Flavor for '%s' rackspace role should be selected on 'Placement and type' tab"), $dbRole->name), $role['farm_role_id']);
                     }
                     break;
             }
             if ($role['settings'][Scalr_Role_Behavior::ROLE_BASE_CUSTOM_TAGS] && PlatformFactory::isOpenstack($role['platform'])) {
                 $reservedBaseCustomTags = ['scalr-meta', 'farmid', 'role', 'httpproto', 'region', 'hash', 'realrolename', 'szr_key', 'serverid', 'p2p_producer_endpoint', 'queryenv_url', 'behaviors', 'farm_roleid', 'roleid', 'env_id', 'platform', 'server_index', 'cloud_server_id', 'cloud_location_zone', 'owner_email'];
                 $baseCustomTags = @explode("\n", $role['settings'][Scalr_Role_Behavior::ROLE_BASE_CUSTOM_TAGS]);
                 foreach ((array) $baseCustomTags as $tag) {
                     $tag = trim($tag);
                     $tagChunks = explode("=", $tag);
                     if (in_array(trim($tagChunks[0]), $reservedBaseCustomTags)) {
                         $this->setBuildError(Scalr_Role_Behavior::ROLE_BASE_CUSTOM_TAGS, "Avoid using Scalr-reserved metadata names.", $role['farm_role_id']);
                     }
                 }
             }
             if ($role['settings'][Scalr_Role_Behavior::ROLE_BASE_HOSTNAME_FORMAT]) {
                 if (!preg_match('/^[A-Za-z0-9\\{\\}_\\.-]+$/si', $role['settings'][Scalr_Role_Behavior::ROLE_BASE_HOSTNAME_FORMAT])) {
                     $this->setBuildError(Scalr_Role_Behavior::ROLE_BASE_HOSTNAME_FORMAT, "server hostname format for role'{$dbRole->name}' should contain only [a-z0-9-] chars. First char should not be hypen.", $role['farm_role_id']);
                 }
             }
             if ($role['settings'][DBFarmRole::SETTING_DNS_CREATE_RECORDS]) {
                 if ($role['settings'][DBFarmRole::SETTING_DNS_EXT_RECORD_ALIAS]) {
                     if (!preg_match('/^[A-Za-z0-9\\{\\}_\\.-]+$/si', $role['settings'][DBFarmRole::SETTING_DNS_EXT_RECORD_ALIAS])) {
                         $this->setBuildError(DBFarmRole::SETTING_DNS_EXT_RECORD_ALIAS, "ext- record alias for role '{$dbRole->name}' should contain only [A-Za-z0-9-] chars. First and last char should not be hypen.", $role['farm_role_id']);
                     }
                 }
                 if ($role['settings'][DBFarmRole::SETTING_DNS_INT_RECORD_ALIAS]) {
                     if (!preg_match('/^[A-Za-z0-9\\{\\}_\\.-]+$/si', $role['settings'][DBFarmRole::SETTING_DNS_INT_RECORD_ALIAS])) {
                         $this->setBuildError(DBFarmRole::SETTING_DNS_INT_RECORD_ALIAS, "int- record alias for role '{$dbRole->name}' should contain only [A-Za-z0-9-] chars. First and last char should not by hypen.", $role['farm_role_id']);
                     }
                 }
             }
             //DEPRECATED
             $rParams = $dbRole->getParameters();
             if (count($rParams) > 0 && strpos($role['farm_role_id'], 'virtual_') === false) {
                 if (empty($role['params'])) {
                     try {
                         $dbFarmRole = DBFarmRole::LoadByID($role['farm_role_id']);
                         foreach ($rParams as $param) {
                             $farmRoleOption = $this->db->GetRow("SELECT id, value FROM farm_role_options WHERE farm_roleid=? AND `hash`=? LIMIT 1", array($dbFarmRole->ID, $param['hash']));
                             if ($farmRoleOption['id']) {
                                 $value = $farmRoleOption['value'];
                             }
                             $role['params'][$param['hash']] = $value;
                         }
                     } catch (Exception $e) {
                     }
                 }
             }
             //Validate role parameters
             foreach ($rParams as $p) {
                 if ($p['required'] && $role['params'][$p['hash']] == "" && !$p['defval']) {
                     $this->setBuildError($p['name'], "Missed required parameter '{$p['name']}' for role '{$dbRole->name}'", $role['farm_role_id']);
                 }
             }
             // Validate Global variables
             if (!strstr($role['farm_role_id'], 'virtual_')) {
                 $farmRole = DBFarmRole::LoadByID($role['farm_role_id']);
             } else {
                 $farmRole = null;
             }
             $result = $farmRoleVariables->validateValues(is_array($role['variables']) ? $role['variables'] : [], $dbRole->id, $farmId, $farmRole ? $farmRole->ID : 0);
             if ($result !== TRUE) {
                 $this->setBuildError('variables', $result, $role['farm_role_id']);
             }
         }
     }
     if ($farmSettings['vpc_id']) {
         if (!$hasVpcRouter && $vpcRouterRequired) {
             $this->setBuildError(DBFarmRole::SETTING_AWS_VPC_SUBNET_ID, 'You must select a VPC Router for Farm Roles launched in a Private VPC Subnet', $vpcRouterRequired);
         }
     }
     if ($this->getContainer()->analytics->enabled && $this->request->isInterfaceBetaOrNotHostedScalr()) {
         if ($farmSettings['projectId']) {
             $project = $this->getContainer()->analytics->projects->get($farmSettings['projectId']);
             if (!$project) {
                 $this->setBuildError('projectId', 'Project not found', null);
             } else {
                 if ($project->ccId != $this->getEnvironment()->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID)) {
                     $this->setBuildError('projectId', 'Invalid project identifier. Project should correspond to the Environment\'s cost center.', null);
                 }
             }
         } else {
             $this->setBuildError('projectId', 'Project field is required', null);
         }
     }
     return $this->errors['error_count'] == 0 ? true : false;
 }
Beispiel #7
0
 public function xBuildAction()
 {
     $this->request->defineParams(array('farmId' => array('type' => 'int'), 'roles' => array('type' => 'json'), 'farm' => array('type' => 'json'), 'roleUpdate' => array('type' => 'int')));
     $Validator = new Validator();
     $cloudFoundryStack = array();
     $nginxFound = 0;
     foreach ($this->getParam('roles') as $role) {
         $dbRole = DBRole::loadById($role['role_id']);
         if (!$dbRole->getImageId($role['platform'], $role['cloud_location'])) {
             throw new Exception(sprintf(_("Role '%s' is not available in %s on %s"), $dbRole->name, $role['platform'], $role['cloud_location']));
         }
         // Validate deployments
         $appId = $role[Scalr_Role_Behavior::ROLE_DM_APPLICATION_ID];
         if ($appId) {
             $application = Scalr_Dm_Application::init()->loadById($appId);
             $this->user->getPermissions()->validate($application);
             if (!$role[Scalr_Role_Behavior::ROLE_DM_REMOTE_PATH]) {
                 throw new Exception(sprintf("Remote path reuired for deployment on role '%s'", $dbRole->name));
             }
         }
         //-- CloudFoundryStuff
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER)) {
             $cloudFoundryStack[ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER] = true;
         }
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_DEA)) {
             $cloudFoundryStack[ROLE_BEHAVIORS::CF_DEA] = true;
         }
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_HEALTH_MANAGER)) {
             $cloudFoundryStack[ROLE_BEHAVIORS::CF_HEALTH_MANAGER] = true;
         }
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_ROUTER)) {
             $cloudFoundryStack[ROLE_BEHAVIORS::CF_ROUTER] = true;
         }
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_SERVICE)) {
             $cloudFoundryStack[ROLE_BEHAVIORS::CF_SERVICE] = true;
         }
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::NGINX)) {
             $nginxFound++;
         }
         //-- End CloudFoundry stuff
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) {
             $role['settings'][DBFarmRole::SETTING_SCALING_MAX_INSTANCES] = $role['settings'][DBFarmRole::SETTING_SCALING_MIN_INSTANCES];
             $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] = (int) $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO];
             if ($role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] < 1 || $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] > 100) {
                 throw new Exception(sprintf("Nodes ratio for RabbitMq role '%s' should be between 1 and 100", $dbRole->name));
             }
         }
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MONGODB)) {
             if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_ENGINE] == 'ebs') {
                 if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] < 10 || $role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] > 1000) {
                     throw new Exception(sprintf("EBS size for mongoDB role should be between 10 and 1000 GB", $dbRole->name));
                 }
             }
         }
         /* Validate scaling */
         $minCount = (int) $role['settings'][DBFarmRole::SETTING_SCALING_MIN_INSTANCES];
         if (!$minCount && $minCount != 0) {
             $minCount = 1;
         }
         if ($minCount < 0 || $minCount > 400) {
             throw new Exception(sprintf(_("Min instances for '%s' must be a number between 1 and 400"), $dbRole->name));
         }
         $maxCount = (int) $role['settings'][DBFarmRole::SETTING_SCALING_MAX_INSTANCES];
         if (!$maxCount) {
             $maxCount = 1;
         }
         if ($maxCount < 1 || $maxCount > 400) {
             throw new Exception(sprintf(_("Max instances for '%s' must be a number between 1 and 400"), $dbRole->name));
         }
         if ($maxCount < $minCount) {
             throw new Exception(sprintf(_("Max instances should be greater or equal than Min instances for role '%s'"), $dbRole->name));
         }
         if (isset($role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL]) && $role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL] > 0) {
             $polling_interval = (int) $role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL];
         } else {
             $polling_interval = 2;
         }
         if ($polling_interval < 1 || $polling_interval > 50) {
             throw new Exception(sprintf(_("Polling interval for role '%s' must be a number between 1 and 50"), $dbRole->name));
         }
         /** Validate platform specified settings **/
         switch ($role['platform']) {
             case SERVER_PLATFORMS::EC2:
                 Modules_Platforms_Ec2_Helpers_Ebs::farmValidateRoleSettings($role['settings'], $dbRole->name);
                 Modules_Platforms_Ec2_Helpers_Eip::farmValidateRoleSettings($role['settings'], $dbRole->name);
                 Modules_Platforms_Ec2_Helpers_Elb::farmValidateRoleSettings($role['settings'], $dbRole->name);
                 if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MYSQL)) {
                     if ($role['settings'][DBFarmRole::SETTING_MYSQL_DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EBS) {
                         if ($dbRole->generation != 2) {
                             if ($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == "" || $role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == "x-scalr-diff" || stristr($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE], 'x-scalr-custom')) {
                                 throw new Exception(sprintf(_("Requirement for EBS MySQL data storage is specific 'Placement' parameter for role '%s'"), $dbRole->name));
                             }
                         }
                     }
                 }
                 if ($dbRole->getDbMsrBehavior()) {
                     if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EPH) {
                         if (!$role['settings'][Scalr_Db_Msr::DATA_STORAGE_EPH_DISK]) {
                             throw new Exception(sprintf(_("Ephemeral disk settings is required for role '%s'"), $dbRole->name));
                         }
                     }
                 }
                 if ($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == 'x-scalr-custom=') {
                     throw new Exception(sprintf(_("Availability zone for role \"%s\" should be selected"), $dbRole->name));
                 }
                 break;
             case SERVER_PLATFORMS::RDS:
                 Modules_Platforms_Rds_Helpers_Rds::farmValidateRoleSettings($role['settings'], $dbRole->name);
                 break;
             case SERVER_PLATFORMS::EUCALYPTUS:
                 Modules_Platforms_Eucalyptus_Helpers_Eucalyptus::farmValidateRoleSettings($role['settings'], $dbRole->name);
                 break;
             case SERVER_PLATFORMS::CLOUDSTACK:
                 Modules_Platforms_Cloudstack_Helpers_Cloudstack::farmValidateRoleSettings($role['settings'], $dbRole->name);
                 break;
             case SERVER_PLATFORMS::RACKSPACE:
                 Modules_Platforms_Rackspace_Helpers_Rackspace::farmValidateRoleSettings($role['settings'], $dbRole->name);
                 break;
         }
         Scalr_Helpers_Dns::farmValidateRoleSettings($role['settings'], $dbRole->name);
     }
     //Validate ClouFoundry stuff
     if (!empty($cloudFoundryStack)) {
         if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER]) {
             throw new Exception("CF CloudContoller role required for CloudFoundry stack. Please add All-in-one CF or separate CCHM role to farm");
         }
         if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_HEALTH_MANAGER]) {
             throw new Exception("CF HealthManager role required for CloudFoundry stack. Please add All-in-one CF or separate CCHM role to farm");
         }
         if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_ROUTER]) {
             throw new Exception("CF Router role required for CloudFoundry stack. Please add All-in-one CF or separate CF Router role to farm");
         }
         if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_DEA]) {
             throw new Exception("CF DEA role required for CloudFoundry stack. Please add All-in-one CF or separate CF DEA role to farm");
         }
         if (!$nginxFound) {
             throw new Exception("Nginx load balancer role required for CloudFoundry stack. Please add it to the farm");
         }
         if ($cloudFoundryStack[ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER] > 1) {
             throw new Exception("CloudFoundry stack can work only with ONE CF CloudController role. Please leave only one CloudController role in farm");
         }
         if ($cloudFoundryStack[ROLE_BEHAVIORS::CF_HEALTH_MANAGER] > 1) {
             throw new Exception("CloudFoundry stack can work only with ONE CF HealthManager role. Please leave only one HealthManager role in farm");
         }
         if ($nginxFound > 1) {
             throw new Exception("CloudFoundry stack can work only with ONE nginx role. Please leave only one nginx role in farm");
         }
     }
     $client = Client::Load($this->user->getAccountId());
     if ($this->getParam('farmId')) {
         $dbFarm = DBFarm::LoadByID($this->getParam('farmId'));
         $this->user->getPermissions()->validate($dbFarm);
     } else {
         $this->user->getAccount()->validateLimit(Scalr_Limits::ACCOUNT_FARMS, 1);
         $dbFarm = new DBFarm();
         $dbFarm->Status = FARM_STATUS::TERMINATED;
     }
     if ($this->getParam('farm')) {
         $farm = $this->getParam('farm');
         $dbFarm->Name = strip_tags($farm['name']);
         $dbFarm->RolesLaunchOrder = $farm['roles_launch_order'];
         $dbFarm->Comments = trim(strip_tags($farm['description']));
     }
     if (!$Validator->IsNotEmpty($dbFarm->Name)) {
         throw new Exception(_("Farm name required"));
     }
     $dbFarm->save();
     if (!$dbFarm->GetSetting(DBFarm::SETTING_CRYPTO_KEY)) {
         $dbFarm->SetSetting(DBFarm::SETTING_CRYPTO_KEY, Scalr::GenerateRandomKey(40));
     }
     $usedPlatforms = array();
     $dbFarmRolesList = array();
     $newFarmRolesList = array();
     foreach ($this->getParam('roles') as $role) {
         if ($role['farm_role_id']) {
             $update = true;
             $dbFarmRole = DBFarmRole::LoadByID($role['farm_role_id']);
             $dbRole = DBRole::loadById($dbFarmRole->RoleID);
             $role['role_id'] = $dbFarmRole->RoleID;
         } else {
             $update = false;
             $dbRole = DBRole::loadById($role['role_id']);
             $dbFarmRole = $dbFarm->AddRole($dbRole, $role['platform'], $role['cloud_location'], (int) $role['launch_index']);
         }
         if ($dbRole->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) {
             $role['settings'][DBFarmRole::SETTING_SCALING_MAX_INSTANCES] = $role['settings'][DBFarmRole::SETTING_SCALING_MIN_INSTANCES];
         }
         if ($dbFarmRole->NewRoleID) {
             continue;
         }
         if ($update) {
             $dbFarmRole->LaunchIndex = (int) $role['launch_index'];
             $dbFarmRole->Save();
         }
         $usedPlatforms[$role['platform']] = 1;
         $oldRoleSettings = $dbFarmRole->GetAllSettings();
         foreach ($role['scaling_settings'] as $k => $v) {
             $dbFarmRole->SetSetting($k, $v);
         }
         foreach ($role['settings'] as $k => $v) {
             $dbFarmRole->SetSetting($k, $v);
         }
         /****** Scaling settings ******/
         $scalingManager = new Scalr_Scaling_Manager($dbFarmRole);
         $scalingManager->setFarmRoleMetrics($role['scaling']);
         //TODO: optimize this code...
         $this->db->Execute("DELETE FROM farm_role_scaling_times WHERE farm_roleid=?", array($dbFarmRole->ID));
         // 5 = Time based scaling -> move to constants
         if ($role['scaling'][5]) {
             foreach ($role['scaling'][5] as $scal_period) {
                 $chunks = explode(":", $scal_period['id']);
                 $this->db->Execute("INSERT INTO farm_role_scaling_times SET\n\t\t\t\t\t\tfarm_roleid\t\t= ?,\n\t\t\t\t\t\tstart_time\t\t= ?,\n\t\t\t\t\t\tend_time\t\t= ?,\n\t\t\t\t\t\tdays_of_week\t= ?,\n\t\t\t\t\t\tinstances_count\t= ?\n\t\t\t\t\t", array($dbFarmRole->ID, $chunks[0], $chunks[1], $chunks[2], $chunks[3]));
             }
         }
         /*****************/
         /* Update role params */
         $dbFarmRole->SetParameters($role['params']);
         /* End of role params management */
         /* Add script options to databse */
         $dbFarmRole->SetScripts($role['scripting']);
         /* End of scripting section */
         /* Add services configuration */
         $dbFarmRole->SetServiceConfigPresets($role['config_presets']);
         /* End of scripting section */
         Scalr_Helpers_Dns::farmUpdateRoleSettings($dbFarmRole, $oldRoleSettings, $role['settings']);
         foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) {
             $behavior->onFarmSave($dbFarm, $dbFarmRole);
         }
         /**
          * Platfrom specified updates
          */
         if ($dbFarmRole->Platform == SERVER_PLATFORMS::EC2) {
             Modules_Platforms_Ec2_Helpers_Ebs::farmUpdateRoleSettings($dbFarmRole, $oldRoleSettings, $role['settings']);
             Modules_Platforms_Ec2_Helpers_Eip::farmUpdateRoleSettings($dbFarmRole, $oldRoleSettings, $role['settings']);
             Modules_Platforms_Ec2_Helpers_Elb::farmUpdateRoleSettings($dbFarmRole, $oldRoleSettings, $role['settings']);
         }
         $dbFarmRolesList[] = $dbFarmRole;
         $newFarmRolesList[] = $dbFarmRole->ID;
     }
     if (!$this->getParam('roleUpdate')) {
         foreach ($dbFarm->GetFarmRoles() as $dbFarmRole) {
             if (!$dbFarmRole->NewRoleID && !in_array($dbFarmRole->ID, $newFarmRolesList)) {
                 $dbFarmRole->Delete();
             }
         }
     }
     if ($usedPlatforms[SERVER_PLATFORMS::CLOUDSTACK]) {
         Modules_Platforms_Cloudstack_Helpers_Cloudstack::farmSave($dbFarm, $dbFarmRolesList);
     }
     if ($usedPlatforms[SERVER_PLATFORMS::EC2]) {
         Modules_Platforms_Ec2_Helpers_Ec2::farmSave($dbFarm, $dbFarmRolesList);
     }
     if ($usedPlatforms[SERVER_PLATFORMS::EUCALYPTUS]) {
         Modules_Platforms_Eucalyptus_Helpers_Eucalyptus::farmSave($dbFarm, $dbFarmRolesList);
     }
     $dbFarm->save();
     if (!$client->GetSettingValue(CLIENT_SETTINGS::DATE_FARM_CREATED)) {
         $client->SetSettingValue(CLIENT_SETTINGS::DATE_FARM_CREATED, time());
     }
     $this->response->success('Farm successfully saved');
     $this->response->data(array('farmId' => $dbFarm->ID));
 }
Beispiel #8
0
 /**
  *
  * @param array $farmSettings
  * @param array $roles
  * @return bool
  */
 private function isFarmConfigurationValid($farmId, $farmSettings, array $roles = array())
 {
     $this->errors = array('error_count' => 0);
     $farmVariables = new Scalr_Scripting_GlobalVariables($this->getEnvironmentId(), Scalr_Scripting_GlobalVariables::SCOPE_FARM);
     $farmRoleVariables = new Scalr_Scripting_GlobalVariables($this->getEnvironmentId(), Scalr_Scripting_GlobalVariables::SCOPE_FARMROLE);
     if ($farmSettings['variables']) {
         $result = $farmVariables->validateValues($farmSettings['variables'], 0, $farmId);
         if ($result !== TRUE) {
             $this->setBuildError('variables', $result);
         }
     }
     if (!empty($roles)) {
         $cloudFoundryStack = array();
         $hasVpcRouter = false;
         $nginxFound = 0;
         foreach ($roles as $role) {
             $dbRole = DBRole::loadById($role['role_id']);
             if (!$dbRole->getImageId($role['platform'], $role['cloud_location'])) {
                 $this->setBuildError($dbRole->name, sprintf(_("Role '%s' is not available in %s on %s"), $dbRole->name, $role['platform'], $role['cloud_location']), $role['farm_role_id']);
             }
             if ($role['alias']) {
                 if (!preg_match("/^[A-Za-z0-9]+[A-Za-z0-9-]*[A-Za-z0-9]+\$/si", $role['alias'])) {
                     $this->setBuildError('alias', sprintf(_("Alias for role '%s' should start and end with letter or number and contain only letters, numbers and dashes."), $dbRole->name, $role['platform'], $role['cloud_location']), $role['farm_role_id']);
                 }
             }
             // Validate deployments
             $appId = $role[Scalr_Role_Behavior::ROLE_DM_APPLICATION_ID];
             if ($appId) {
                 $application = Scalr_Dm_Application::init()->loadById($appId);
                 $this->user->getPermissions()->validate($application);
                 if (!$role[Scalr_Role_Behavior::ROLE_DM_REMOTE_PATH]) {
                     $this->setBuildError(Scalr_Role_Behavior::ROLE_DM_REMOTE_PATH, sprintf("Remote path required for deployment on role '%s'", $dbRole->name), $role['farm_role_id']);
                 }
             }
             //-- CloudFoundryStuff
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER)) {
                 $cloudFoundryStack[ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER] = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_DEA)) {
                 $cloudFoundryStack[ROLE_BEHAVIORS::CF_DEA] = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_HEALTH_MANAGER)) {
                 $cloudFoundryStack[ROLE_BEHAVIORS::CF_HEALTH_MANAGER] = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_ROUTER)) {
                 $cloudFoundryStack[ROLE_BEHAVIORS::CF_ROUTER] = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CF_SERVICE)) {
                 $cloudFoundryStack[ROLE_BEHAVIORS::CF_SERVICE] = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER)) {
                 $hasVpcRouter = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::NGINX)) {
                 $nginxFound++;
             }
             //-- End CloudFoundry stuff
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) {
                 $role['settings'][DBFarmRole::SETTING_SCALING_MAX_INSTANCES] = $role['settings'][DBFarmRole::SETTING_SCALING_MIN_INSTANCES];
                 $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] = (int) $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO];
                 if ($role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] < 1 || $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] > 100) {
                     $this->setBuildError(Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO, sprintf("Nodes ratio for RabbitMq role '%s' should be between 1 and 100", $dbRole->name), $role['farm_role_id']);
                 }
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MONGODB)) {
                 if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_ENGINE] == 'ebs') {
                     if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] < 10 || $role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] > 1000) {
                         $this->setBuildError(Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE, sprintf("EBS size for mongoDB role should be between 10 and 1000 GB", $dbRole->name), $role['farm_role_id']);
                     }
                 }
             }
             /* Validate scaling */
             $minCount = (int) $role['settings'][DBFarmRole::SETTING_SCALING_MIN_INSTANCES];
             if (!$minCount && $minCount != 0) {
                 $minCount = 1;
             }
             if ($minCount < 0 || $minCount > 400) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_MIN_INSTANCES, sprintf(_("Min instances for '%s' must be a number between 1 and 400"), $dbRole->name), $role['farm_role_id']);
             }
             $maxCount = (int) $role['settings'][DBFarmRole::SETTING_SCALING_MAX_INSTANCES];
             if (!$maxCount) {
                 $maxCount = 1;
             }
             if ($maxCount < 1 || $maxCount > 400) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_MAX_INSTANCES, sprintf(_("Max instances for '%s' must be a number between 1 and 400"), $dbRole->name), $role['farm_role_id']);
             }
             if ($maxCount < $minCount) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_MAX_INSTANCES, sprintf(_("Max instances should be greater or equal than Min instances for role '%s'"), $dbRole->name), $role['farm_role_id']);
             }
             if (isset($role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL]) && $role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL] > 0) {
                 $polling_interval = (int) $role['settings'][DBFarmRole::SETTING_SCALING_POLLING_INTERVAL];
             } else {
                 $polling_interval = 2;
             }
             if ($polling_interval < 1 || $polling_interval > 50) {
                 $this->setBuildError(DBFarmRole::SETTING_SCALING_POLLING_INTERVAL, sprintf(_("Polling interval for role '%s' must be a number between 1 and 50"), $dbRole->name), $role['farm_role_id']);
             }
             /** Validate platform specified settings **/
             switch ($role['platform']) {
                 case SERVER_PLATFORMS::EC2:
                     if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MYSQL)) {
                         if ($role['settings'][DBFarmRole::SETTING_MYSQL_DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EBS) {
                             if ($dbRole->generation != 2) {
                                 if ($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == "" || $role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == "x-scalr-diff" || stristr($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE], 'x-scalr-custom')) {
                                     $this->setBuildError(DBFarmRole::SETTING_AWS_AVAIL_ZONE, sprintf(_("Requirement for EBS MySQL data storage is specific 'Placement' parameter for role '%s'"), $dbRole->name), $role['farm_role_id']);
                                 }
                             }
                         }
                     }
                     if ($dbRole->getDbMsrBehavior()) {
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EPH) {
                             if (!$role['settings'][Scalr_Db_Msr::DATA_STORAGE_EPH_DISK] && !$role['settings'][Scalr_Db_Msr::DATA_STORAGE_EPH_DISKS]) {
                                 $this->setBuildError(Scalr_Db_Msr::DATA_STORAGE_EPH_DISK, sprintf(_("Ephemeral disk settings is required for role '%s'"), $dbRole->name), $role['farm_role_id']);
                             }
                         }
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::LVM) {
                             if (!$role['settings'][Scalr_Role_DbMsrBehavior::ROLE_DATA_STORAGE_LVM_VOLUMES]) {
                                 $this->setBuildError(Scalr_Role_DbMsrBehavior::ROLE_DATA_STORAGE_LVM_VOLUMES, sprintf(_("Ephemeral disks settings is required for role '%s'"), $dbRole->name), $role['farm_role_id']);
                             }
                         }
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::RAID_EBS) {
                             if (!$this->user->getAccount()->isFeatureEnabled(Scalr_Limits::FEATURE_RAID)) {
                                 $this->setBuildError(Scalr_Db_Msr::DATA_STORAGE_ENGINE, 'RAID arrays are not available for your pricing plan. <a href="#/billing">Please upgrade your account to be able to use this feature.</a>', $role['farm_role_id']);
                             }
                         }
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_FSTYPE] && $role['settings'][Scalr_Db_Msr::DATA_STORAGE_FSTYPE] != 'ext3') {
                             if (!$this->user->getAccount()->isFeatureEnabled(Scalr_Limits::FEATURE_MFS)) {
                                 $this->setBuildError(Scalr_Db_Msr::DATA_STORAGE_ENGINE, 'Only ext3 filesystem available for your pricing plan. <a href="#/billing">Please upgrade your account to be able to use other filesystems.</a>', $role['farm_role_id']);
                             }
                         }
                     }
                     if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MONGODB)) {
                         if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::RAID_EBS) {
                             if (!$this->user->getAccount()->isFeatureEnabled(Scalr_Limits::FEATURE_RAID)) {
                                 $this->setBuildError(Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_ENGINE, 'RAID arrays are not available for your pricing plan. <a href="#/billing">Please upgrade your account to be able to use this feature.</a>', $role['farm_role_id']);
                             }
                         }
                     }
                     if ($role['settings'][DBFarmRole::SETTING_AWS_AVAIL_ZONE] == 'x-scalr-custom=') {
                         $this->setBuildError(DBFarmRole::SETTING_AWS_AVAIL_ZONE, sprintf(_("Availability zone for role \"%s\" should be selected"), $dbRole->name), $role['farm_role_id']);
                     }
                     break;
                 case SERVER_PLATFORMS::CLOUDSTACK:
                     if (!$role['settings'][DBFarmRole::SETTING_CLOUDSTACK_SERVICE_OFFERING_ID]) {
                         $this->setBuildError(DBFarmRole::SETTING_CLOUDSTACK_SERVICE_OFFERING_ID, sprintf(_("Service offering for '%s' cloudstack role should be selected on 'Cloudstack settings' tab"), $dbRole->name), $role['farm_role_id']);
                     }
                     break;
                 case SERVER_PLATFORMS::RACKSPACE:
                     if (!$role['settings'][DBFarmRole::SETTING_RS_FLAVOR_ID]) {
                         $this->setBuildError(DBFarmRole::SETTING_CLOUDSTACK_SERVICE_OFFERING_ID, sprintf(_("Flavor for '%s' rackspace role should be selected on 'Placement and type' tab"), $dbRole->name), $role['farm_role_id']);
                     }
                     break;
             }
             if ($role['settings'][DBFarmRole::SETTING_DNS_CREATE_RECORDS]) {
                 if ($role['settings'][DBFarmRole::SETTING_DNS_EXT_RECORD_ALIAS]) {
                     if (!preg_match("/^[A-Za-z0-9-%_]+\$/si", $role['settings'][DBFarmRole::SETTING_DNS_EXT_RECORD_ALIAS])) {
                         $this->setBuildError(DBFarmRole::SETTING_DNS_EXT_RECORD_ALIAS, "ext-%rolename% record alias for role '{$dbRole->name}' should contain only [A-Za-z0-9-] chars. First and last char should not by hypen.", $role['farm_role_id']);
                     }
                 }
                 if ($role['settings'][DBFarmRole::SETTING_DNS_INT_RECORD_ALIAS]) {
                     if (!preg_match("/^[A-Za-z0-9-%_]+\$/si", $role['settings'][DBFarmRole::SETTING_DNS_INT_RECORD_ALIAS])) {
                         $this->setBuildError(DBFarmRole::SETTING_DNS_INT_RECORD_ALIAS, "int-%rolename% record alias for role '{$dbRole->name}' should contain only [A-Za-z0-9-] chars. First and last char should not by hypen.", $role['farm_role_id']);
                     }
                 }
             }
             //DEPRECATED
             $rParams = $dbRole->getParameters();
             if (count($rParams) > 0 && strpos($role['farm_role_id'], 'virtual_') === false) {
                 if (empty($role['params'])) {
                     try {
                         $dbFarmRole = DBFarmRole::LoadByID($role['farm_role_id']);
                         foreach ($rParams as $param) {
                             $farmRoleOption = $this->db->GetRow("SELECT id, value FROM farm_role_options WHERE farm_roleid=? AND `hash`=? LIMIT 1", array($dbFarmRole->ID, $param['hash']));
                             if ($farmRoleOption['id']) {
                                 $value = $farmRoleOption['value'];
                             }
                             $role['params'][$param['hash']] = $value;
                         }
                     } catch (Exception $e) {
                     }
                 }
             }
             //Validate role parameters
             foreach ($rParams as $p) {
                 if ($p['required'] && $role['params'][$p['hash']] == "" && !$p['defval']) {
                     $this->setBuildError($p['name'], "Missed required parameter '{$p['name']}' for role '{$dbRole->name}'", $role['farm_role_id']);
                 }
             }
             // Validate Global variables
             if (!strstr($role['farm_role_id'], 'virtual_')) {
                 $farmRole = DBFarmRole::LoadByID($role['farm_role_id']);
             } else {
                 $farmRole = null;
             }
             $result = $farmRoleVariables->validateValues($role['variables'], $dbRole->id, $farmId, $farmRole ? $farmRole->ID : 0);
             if ($result !== TRUE) {
                 $this->setBuildError('variables', $result, $role['farm_role_id']);
             }
         }
     }
     try {
         if (!empty($cloudFoundryStack)) {
             if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER]) {
                 throw new Exception("CF CloudContoller role required for CloudFoundry stack. Please add All-in-one CF or separate CCHM role to farm");
             }
             if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_HEALTH_MANAGER]) {
                 throw new Exception("CF HealthManager role required for CloudFoundry stack. Please add All-in-one CF or separate CCHM role to farm");
             }
             if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_ROUTER]) {
                 throw new Exception("CF Router role required for CloudFoundry stack. Please add All-in-one CF or separate CF Router role to farm");
             }
             if (!$cloudFoundryStack[ROLE_BEHAVIORS::CF_DEA]) {
                 throw new Exception("CF DEA role required for CloudFoundry stack. Please add All-in-one CF or separate CF DEA role to farm");
             }
             if (!$nginxFound) {
                 throw new Exception("Nginx load balancer role required for CloudFoundry stack. Please add it to the farm");
             }
             if ($cloudFoundryStack[ROLE_BEHAVIORS::CF_CLOUD_CONTROLLER] > 1) {
                 throw new Exception("CloudFoundry stack can work only with ONE CF CloudController role. Please leave only one CloudController role in farm");
             }
             if ($cloudFoundryStack[ROLE_BEHAVIORS::CF_HEALTH_MANAGER] > 1) {
                 throw new Exception("CloudFoundry stack can work only with ONE CF HealthManager role. Please leave only one HealthManager role in farm");
             }
             if ($nginxFound > 1) {
                 throw new Exception("CloudFoundry stack can work only with ONE nginx role. Please leave only one nginx role in farm");
             }
         }
     } catch (Exception $e) {
         $this->setBuildError('general', $e->getMessage(), null);
     }
     if ($farmSettings['vpc_id']) {
         $vpcRouterRequired = false;
         if (\Scalr::config('scalr.instances_connection_policy') != 'local' && !$hasVpcRouter) {
             foreach ($this->getParam('roles') as $role) {
                 if ($role['settings'][DBFarmRole::SETTING_AWS_VPC_INTERNET_ACCESS] == 'outbound-only') {
                     $vpcRouterRequired = true;
                     break;
                 }
             }
             if ($vpcRouterRequired) {
                 $this->setBuildError('general', "VPC Router role required for farm that running inside VPC with roles configured for outbound-only internet access", null);
             }
         }
     }
     return $this->errors['error_count'] == 0 ? true : false;
 }
Beispiel #9
0
 /**
  *
  * @param array $farmSettings
  * @param array $roles
  * @return bool
  */
 private function isFarmConfigurationValid($farmId, $farmSettings, array $roles = array())
 {
     $this->errors = array('error_count' => 0);
     $farmVariables = 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);
     $name = $this->request->stripValue($farmSettings['name']);
     if (empty($name)) {
         $this->setBuildError('name', 'Farm name is invalid');
     }
     if ($farmSettings['variables']) {
         $result = $farmVariables->validateValues(is_array($farmSettings['variables']) ? $farmSettings['variables'] : [], 0, $farmId);
         if ($result !== TRUE) {
             $this->setBuildError('variables', $result);
         }
     }
     if (is_numeric($farmSettings['owner'])) {
         try {
             $u = (new Scalr_Account_User())->loadById($farmSettings['owner']);
             if ($u->getAccountId() != $this->user->getAccountId()) {
                 throw new Exception('User not found');
             }
         } catch (Exception $e) {
             $this->setBuildError('owner', $e->getMessage());
         }
     }
     if (is_numeric($farmSettings['teamOwner']) && $farmSettings['teamOwner'] > 0) {
         if ($this->user->canManageAcl()) {
             $teams = $this->db->getAll('SELECT id, name FROM account_teams WHERE account_id = ?', array($this->user->getAccountId()));
         } else {
             $teams = $this->user->getTeams();
         }
         if (!in_array($farmSettings['teamOwner'], array_map(function ($t) {
             return $t['id'];
         }, $teams))) {
             if ($this->db->GetOne('SELECT team_id FROM farms WHERE id = ?', [$farmId]) != $farmSettings['teamOwner']) {
                 $this->setBuildError('teamOwner', 'Team not found');
             }
         }
     }
     if (!empty($roles)) {
         $hasVpcRouter = false;
         $vpcRouterRequired = false;
         $governance = new Scalr_Governance($this->getEnvironmentId());
         foreach ($roles as $role) {
             $dbRole = DBRole::loadById($role['role_id']);
             if (!$this->hasPermissions($dbRole->__getNewRoleObject())) {
                 $this->setBuildError($dbRole->name, 'You don\'t have access to this role');
             }
             try {
                 $dbRole->__getNewRoleObject()->getImage($role['platform'], $role['cloud_location']);
             } catch (Exception $e) {
                 $this->setBuildError($dbRole->name, sprintf("Role '%s' is not available in %s on %s", $dbRole->name, $role['platform'], $role['cloud_location']));
             }
             if ($role['alias']) {
                 if (!preg_match("/^[[:alnum:]](?:-*[[:alnum:]])*\$/", $role['alias'])) {
                     $this->setBuildError('alias', 'Alias should start and end with letter or number and contain only letters, numbers and dashes.', $role['farm_role_id']);
                 }
             }
             // Validate deployments
             if (isset($role[Scalr_Role_Behavior::ROLE_DM_APPLICATION_ID])) {
                 $application = Scalr_Dm_Application::init()->loadById($role[Scalr_Role_Behavior::ROLE_DM_APPLICATION_ID]);
                 $this->user->getPermissions()->validate($application);
                 if (!$role[Scalr_Role_Behavior::ROLE_DM_REMOTE_PATH]) {
                     $this->setBuildError(Scalr_Role_Behavior::ROLE_DM_REMOTE_PATH, 'Remote path is required for deployment', $role['farm_role_id']);
                 }
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER)) {
                 $hasVpcRouter = true;
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) {
                 $role['settings'][Entity\FarmRoleSetting::SCALING_MAX_INSTANCES] = $role['settings'][Entity\FarmRoleSetting::SCALING_MIN_INSTANCES];
                 $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] = (int) $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO];
                 if ($role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] < 1 || $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO] > 100) {
                     $this->setBuildError(Scalr_Role_Behavior_RabbitMQ::ROLE_NODES_RATIO, 'Nodes ratio should be an integer between 1 and 100', $role['farm_role_id']);
                 } else {
                     $this->checkInteger($role['farm_role_id'], Scalr_Role_Behavior_RabbitMQ::ROLE_DATA_STORAGE_EBS_SIZE, $role['settings'][Scalr_Role_Behavior_RabbitMQ::ROLE_DATA_STORAGE_EBS_SIZE], 'Storage size', 1, 1000);
                 }
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MONGODB)) {
                 if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_ENGINE] == 'ebs') {
                     if ($role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] < 10 || $role['settings'][Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE] > 1000) {
                         $this->setBuildError(Scalr_Role_Behavior_MongoDB::ROLE_DATA_STORAGE_EBS_SIZE, sprintf("EBS size for mongoDB role should be between 10 and 1000 GB", $dbRole->name), $role['farm_role_id']);
                     }
                 }
             }
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::NGINX)) {
                 $proxies = (array) @json_decode($role['settings'][Scalr_Role_Behavior_Nginx::ROLE_PROXIES], true);
                 foreach ($proxies as $proxyIndex => $proxy) {
                     if ($proxy['ssl'] == 1) {
                         if (empty($proxy['ssl_certificate_id'])) {
                             $this->setBuildError(Scalr_Role_Behavior_Nginx::ROLE_PROXIES, ['message' => 'SSL certificate is required', 'invalidIndex' => $proxyIndex], $role['farm_role_id']);
                             break;
                         }
                         if ($proxy['port'] == $proxy['ssl_port']) {
                             $this->setBuildError(Scalr_Role_Behavior_Nginx::ROLE_PROXIES, ['message' => 'HTTP and HTTPS ports cannot be the same', 'invalidIndex' => $proxyIndex], $role['farm_role_id']);
                         }
                     }
                     if (count($proxy['backends']) > 0) {
                         foreach ($proxy['backends'] as $backend) {
                             if (empty($backend['farm_role_id']) && empty($backend['farm_role_alias']) && empty($backend['host'])) {
                                 $this->setBuildError(Scalr_Role_Behavior_Nginx::ROLE_PROXIES, ['message' => 'Destination is required', 'invalidIndex' => $proxyIndex], $role['farm_role_id']);
                                 break;
                             }
                         }
                     }
                 }
             }
             /* Validate scaling */
             if (!$dbRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER) && !$dbRole->hasBehavior(ROLE_BEHAVIORS::MONGODB)) {
                 $minCount = $this->checkInteger($role['farm_role_id'], Entity\FarmRoleSetting::SCALING_MIN_INSTANCES, $role['settings'][Entity\FarmRoleSetting::SCALING_MIN_INSTANCES], 'Min instances', 0, 400);
                 $maxCount = $this->checkInteger($role['farm_role_id'], Entity\FarmRoleSetting::SCALING_MAX_INSTANCES, $role['settings'][Entity\FarmRoleSetting::SCALING_MAX_INSTANCES], 'Max instances', 1, 400);
                 if ($minCount !== false && $maxCount !== false && $maxCount < $minCount) {
                     $this->setBuildError(Entity\FarmRoleSetting::SCALING_MAX_INSTANCES, 'Max instances should be greater than or equal to Min instances', $role['farm_role_id']);
                 }
                 $this->checkInteger($role['farm_role_id'], Entity\FarmRoleSetting::SCALING_POLLING_INTERVAL, $role['settings'][Entity\FarmRoleSetting::SCALING_POLLING_INTERVAL], 'Polling interval', 1, 50);
                 if (array_key_exists(Entity\FarmRoleSetting::SCALING_UPSCALE_TIMEOUT_ENABLED, $role["settings"]) && $role['settings'][Entity\FarmRoleSetting::SCALING_UPSCALE_TIMEOUT_ENABLED] == 1) {
                     $this->checkInteger($role['farm_role_id'], Entity\FarmRoleSetting::SCALING_UPSCALE_TIMEOUT, $role['settings'][Entity\FarmRoleSetting::SCALING_UPSCALE_TIMEOUT], 'Upscale timeout', 1);
                 }
                 if (array_key_exists(Entity\FarmRoleSetting::SCALING_DOWNSCALE_TIMEOUT_ENABLED, $role["settings"]) && $role['settings'][Entity\FarmRoleSetting::SCALING_DOWNSCALE_TIMEOUT_ENABLED] == 1) {
                     $this->checkInteger($role['farm_role_id'], Entity\FarmRoleSetting::SCALING_DOWNSCALE_TIMEOUT, $role['settings'][Entity\FarmRoleSetting::SCALING_DOWNSCALE_TIMEOUT], 'Downscale timeout', 1);
                 }
                 if (is_array($role['scaling'])) {
                     foreach ($role['scaling'] as $metricId => $metricSettings) {
                         $hasError = false;
                         if ($metricId == Entity\ScalingMetric::METRIC_URL_RESPONSE_TIME_ID) {
                             $hasError = Validator::validateUrl($metricSettings['url']) !== true || Validator::validateInteger($metricSettings['min']) !== true || Validator::validateInteger($metricSettings['max']) !== true;
                         } elseif ($metricId == Entity\ScalingMetric::METRIC_SQS_QUEUE_SIZE_ID) {
                             $hasError = Validator::validateNotEmpty($metricSettings['queue_name']) !== true || Validator::validateInteger($metricSettings['min']) !== true || Validator::validateInteger($metricSettings['max']) !== true;
                         } elseif (in_array($metricId, [Entity\ScalingMetric::METRIC_LOAD_AVERAGES_ID, Entity\ScalingMetric::METRIC_FREE_RAM_ID, Entity\ScalingMetric::METRIC_BANDWIDTH_ID])) {
                             $hasError = Validator::validateFloat($metricSettings['min']) !== true || Validator::validateFloat($metricSettings['max']) !== true;
                         }
                         if ($hasError) {
                             $this->setBuildError('scaling', ['message' => 'Scaling metric settings are invalid', 'invalidIndex' => $metricId], $role['farm_role_id']);
                             break;
                         }
                     }
                 }
             }
             /* Validate advanced settings */
             if (!$dbRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER)) {
                 if (isset($role['settings'][Scalr_Role_Behavior::ROLE_BASE_API_PORT])) {
                     $this->checkInteger($role['farm_role_id'], Scalr_Role_Behavior::ROLE_BASE_API_PORT, $role['settings'][Scalr_Role_Behavior::ROLE_BASE_API_PORT], 'Scalarizr API port', 1, 65535);
                 }
                 if (isset($role['settings'][Scalr_Role_Behavior::ROLE_BASE_MESSAGING_PORT])) {
                     $this->checkInteger($role['farm_role_id'], Scalr_Role_Behavior::ROLE_BASE_MESSAGING_PORT, $role['settings'][Scalr_Role_Behavior::ROLE_BASE_MESSAGING_PORT], 'Scalarizr control port', 1, 65535);
                 }
                 if (isset($role['settings'][Entity\FarmRoleSetting::SYSTEM_REBOOT_TIMEOUT])) {
                     $this->checkInteger($role['farm_role_id'], Entity\FarmRoleSetting::SYSTEM_REBOOT_TIMEOUT, $role['settings'][Entity\FarmRoleSetting::SYSTEM_REBOOT_TIMEOUT], 'Reboot timeout', 1);
                 }
                 if (isset($role['settings'][Entity\FarmRoleSetting::SYSTEM_LAUNCH_TIMEOUT])) {
                     $this->checkInteger($role['farm_role_id'], Entity\FarmRoleSetting::SYSTEM_LAUNCH_TIMEOUT, $role['settings'][Entity\FarmRoleSetting::SYSTEM_LAUNCH_TIMEOUT], 'Launch timeout', 1);
                 }
             }
             /* Validate chef settings */
             if ($dbRole->hasBehavior(ROLE_BEHAVIORS::CHEF)) {
                 if ($role['settings'][Scalr_Role_Behavior_Chef::ROLE_CHEF_BOOTSTRAP] == 1) {
                     if (empty($role['settings'][Scalr_Role_Behavior_Chef::ROLE_CHEF_COOKBOOK_URL]) && empty($role['settings'][Scalr_Role_Behavior_Chef::ROLE_CHEF_SERVER_ID])) {
                         $this->setBuildError(Scalr_Role_Behavior_Chef::ROLE_CHEF_SERVER_ID, 'Chef Server or Chef Solo must be setup if using Chef to bootstrap Role', $role['farm_role_id']);
                     } elseif ($role['settings'][Scalr_Role_Behavior_Chef::ROLE_CHEF_COOKBOOK_URL_TYPE] == 'http' && !empty($role['settings'][Scalr_Role_Behavior_Chef::ROLE_CHEF_COOKBOOK_URL]) && Validator::validateUrl($role['settings'][Scalr_Role_Behavior_Chef::ROLE_CHEF_COOKBOOK_URL]) !== true) {
                         $this->setBuildError(Scalr_Role_Behavior_Chef::ROLE_CHEF_COOKBOOK_URL, 'Cookbook URL is invalid.', $role['farm_role_id']);
                     }
                 } elseif ($dbRole->getProperty(Scalr_Role_Behavior_Chef::ROLE_CHEF_BOOTSTRAP) == 1 && $dbRole->getProperty(Scalr_Role_Behavior_Chef::ROLE_CHEF_SERVER_ID)) {
                     if (strpos($role['farm_role_id'], "virtual_") !== false) {
                         $chefGovernance = $governance->getValue(Scalr_Governance::CATEGORY_GENERAL, Scalr_Governance::GENERAL_CHEF, 'servers');
                         if ($chefGovernance !== null && !isset($chefGovernance[$dbRole->getProperty(Scalr_Role_Behavior_Chef::ROLE_CHEF_SERVER_ID)])) {
                             $this->setBuildError(Scalr_Role_Behavior_Chef::ROLE_CHEF_SERVER_ID, 'Chef server is not allowed by Governance.', $role['farm_role_id']);
                         }
                     }
                     if (empty($dbRole->getProperty(Scalr_Role_Behavior_Chef::ROLE_CHEF_ENVIRONMENT)) && empty($role['settings'][Scalr_Role_Behavior_Chef::ROLE_CHEF_ENVIRONMENT])) {
                         $this->setBuildError(Scalr_Role_Behavior_Chef::ROLE_CHEF_ENVIRONMENT, 'Chef Environment is required', $role['farm_role_id']);
                     }
                 }
             }
             /** Validate platform specified settings **/
             switch ($role['platform']) {
                 case SERVER_PLATFORMS::EC2:
                     if (!empty($role['settings'][Entity\FarmRoleSetting::AWS_TAGS_LIST])) {
                         $reservedBaseCustomTags = ['scalr-meta', 'Name'];
                         $baseCustomTags = @explode("\n", $role['settings'][Entity\FarmRoleSetting::AWS_TAGS_LIST]);
                         foreach ((array) $baseCustomTags as $tag) {
                             $tag = trim($tag);
                             $tagChunks = explode("=", $tag);
                             if (in_array(trim($tagChunks[0]), $reservedBaseCustomTags)) {
                                 $this->setBuildError(Entity\FarmRoleSetting::AWS_TAGS_LIST, "Avoid using Scalr-reserved tag names.", $role['farm_role_id']);
                             }
                         }
                     }
                     if ($dbRole->hasBehavior(ROLE_BEHAVIORS::MYSQL)) {
                         if ($role['settings'][Entity\FarmRoleSetting::MYSQL_DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EBS) {
                             if ($dbRole->generation != 2 && isset($role['settings'][Entity\FarmRoleSetting::AWS_AVAIL_ZONE])) {
                                 if ($role['settings'][Entity\FarmRoleSetting::AWS_AVAIL_ZONE] == "" || $role['settings'][Entity\FarmRoleSetting::AWS_AVAIL_ZONE] == "x-scalr-diff" || stristr($role['settings'][Entity\FarmRoleSetting::AWS_AVAIL_ZONE], 'x-scalr-custom')) {
                                     $this->setBuildError(Entity\FarmRoleSetting::AWS_AVAIL_ZONE, 'Requirement for EBS MySQL data storage is specific \'Placement\' parameter', $role['farm_role_id']);
                                 }
                             }
                         }
                     }
                     if ($dbRole->getDbMsrBehavior()) {
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EPH) {
                             if (!$role['settings'][Scalr_Db_Msr::DATA_STORAGE_EPH_DISK] && !$role['settings'][Scalr_Db_Msr::DATA_STORAGE_EPH_DISKS]) {
                                 $this->setBuildError(Scalr_Db_Msr::DATA_STORAGE_EPH_DISK, 'Ephemeral disk settings is required', $role['farm_role_id']);
                             }
                         } elseif ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::EBS) {
                             if (array_key_exists(Scalr_Db_Msr::DATA_STORAGE_EBS_TYPE, $role["settings"])) {
                                 if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_TYPE] == CreateVolumeRequestData::VOLUME_TYPE_STANDARD) {
                                     $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_STORAGE_EBS_SIZE, $role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_SIZE], 'Storage size', 1, 1024);
                                 } elseif ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_TYPE] == CreateVolumeRequestData::VOLUME_TYPE_GP2) {
                                     $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_STORAGE_EBS_SIZE, $role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_SIZE], 'Storage size', 1, 16384);
                                 } elseif ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_TYPE] == CreateVolumeRequestData::VOLUME_TYPE_IO1) {
                                     $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_STORAGE_EBS_SIZE, $role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_SIZE], 'Storage size', 4, 16384);
                                     $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_STORAGE_EBS_IOPS, $role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_IOPS], 'IOPS', 100, 20000);
                                 }
                             }
                         }
                         if (array_key_exists(Scalr_Db_Msr::DATA_STORAGE_EBS_ENABLE_ROTATION, $role["settings"]) && $role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_ENABLE_ROTATION] == 1) {
                             $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_STORAGE_EBS_ROTATE, $role['settings'][Scalr_Db_Msr::DATA_STORAGE_EBS_ROTATE], 'Snapshot rotation limit', 1);
                         }
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::LVM) {
                             if (!$role['settings'][Scalr_Role_DbMsrBehavior::ROLE_DATA_STORAGE_LVM_VOLUMES]) {
                                 $this->setBuildError(Scalr_Role_DbMsrBehavior::ROLE_DATA_STORAGE_LVM_VOLUMES, 'LVM storage settings is required', $role['farm_role_id']);
                             }
                         }
                     }
                     if ($role['settings'][Entity\FarmRoleSetting::AWS_AVAIL_ZONE] == 'x-scalr-custom=') {
                         $this->setBuildError(Entity\FarmRoleSetting::AWS_AVAIL_ZONE, 'Availability zone should be selected', $role['farm_role_id']);
                     }
                     if (!empty($farmSettings['vpc_id'])) {
                         $sgs = @json_decode($role['settings'][Entity\FarmRoleSetting::AWS_SECURITY_GROUPS_LIST]);
                         if (!$governance->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_SECURITY_GROUPS) && !$dbRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER) && empty($sgs) && empty($role['settings'][Entity\FarmRoleSetting::AWS_SG_LIST])) {
                             $this->setBuildError(Entity\FarmRoleSetting::AWS_SECURITY_GROUPS_LIST, 'Security group(s) should be selected', $role['farm_role_id']);
                         }
                         $subnets = @json_decode($role['settings'][Entity\FarmRoleSetting::AWS_VPC_SUBNET_ID]);
                         if (empty($subnets)) {
                             $this->setBuildError(Entity\FarmRoleSetting::AWS_VPC_SUBNET_ID, 'VPC Subnet(s) should be selected', $role['farm_role_id']);
                         }
                         if (\Scalr::config('scalr.instances_connection_policy') != 'local' && empty($role['settings'][Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID])) {
                             try {
                                 if (!empty($subnets[0])) {
                                     $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2);
                                     $info = $platform->listSubnets($this->getEnvironment(), $role['cloud_location'], $farmSettings['vpc_id'], true, $subnets[0]);
                                     if (!empty($info["type"]) && $info['type'] == 'private') {
                                         $vpcRouterRequired = $role['farm_role_id'];
                                     }
                                 }
                             } catch (Exception $e) {
                             }
                         }
                     }
                     break;
                 case SERVER_PLATFORMS::CLOUDSTACK:
                     if (!$role['settings'][Entity\FarmRoleSetting::CLOUDSTACK_SERVICE_OFFERING_ID]) {
                         $this->setBuildError(Entity\FarmRoleSetting::CLOUDSTACK_SERVICE_OFFERING_ID, 'Service offering should be selected', $role['farm_role_id']);
                     }
                     break;
                 case SERVER_PLATFORMS::RACKSPACE:
                     if (!$role['settings'][Entity\FarmRoleSetting::RS_FLAVOR_ID]) {
                         $this->setBuildError(Entity\FarmRoleSetting::CLOUDSTACK_SERVICE_OFFERING_ID, 'Flavor should be selected', $role['farm_role_id']);
                     }
                     break;
                 case SERVER_PLATFORMS::GCE:
                     if ($dbRole->getDbMsrBehavior()) {
                         if ($role['settings'][Scalr_Db_Msr::DATA_STORAGE_ENGINE] == MYSQL_STORAGE_ENGINE::GCE_PERSISTENT) {
                             $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_STORAGE_GCED_SIZE, $role['settings'][Scalr_Db_Msr::DATA_STORAGE_GCED_SIZE], 'Storage size', 1);
                         }
                     }
                     break;
             }
             if ($dbRole->getDbMsrBehavior()) {
                 if (array_key_exists(Scalr_Db_Msr::DATA_BUNDLE_ENABLED, $role["settings"]) && $role['settings'][Scalr_Db_Msr::DATA_BUNDLE_ENABLED] == 1) {
                     $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_BUNDLE_EVERY, $role['settings'][Scalr_Db_Msr::DATA_BUNDLE_EVERY], 'Bundle period', 1);
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_START_HH, $role['settings'][Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_START_HH], 'Preferred bundle window start HH is invalid', '/^([0-1][0-9])|(2[0-4])$/');
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_START_MM, $role['settings'][Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_START_MM], 'Preferred bundle window start MM is invalid', '/^[0-5][0-9]$/');
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_END_HH, $role['settings'][Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_END_HH], 'Preferred bundle window end HH is invalid', '/^([0-1][0-9])|(2[0-4])$/');
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_END_MM, $role['settings'][Scalr_Db_Msr::DATA_BUNDLE_TIMEFRAME_END_MM], 'Preferred bundle window end MM is invalid', '/^[0-5][0-9]$/');
                 }
                 if (array_key_exists(Scalr_Db_Msr::DATA_BACKUP_ENABLED, $role["settings"]) && $role['settings'][Scalr_Db_Msr::DATA_BACKUP_ENABLED] == 1) {
                     $this->checkInteger($role['farm_role_id'], Scalr_Db_Msr::DATA_BACKUP_EVERY, $role['settings'][Scalr_Db_Msr::DATA_BACKUP_EVERY], 'Backup period', 1);
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_START_HH, $role['settings'][Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_START_HH], 'Preferred backup window start HH is invalid', '/^([0-1][0-9])|(2[0-4])$/');
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_START_MM, $role['settings'][Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_START_MM], 'Preferred backup window start MM is invalid', '/^[0-5][0-9]$/');
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_END_HH, $role['settings'][Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_END_HH], 'Preferred backup window end HH is invalid', '/^([0-1][0-9])|(2[0-4])$/');
                     $this->checkString($role['farm_role_id'], Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_END_MM, $role['settings'][Scalr_Db_Msr::DATA_BACKUP_TIMEFRAME_END_MM], 'Preferred backup window end MM is invalid', '/^[0-5][0-9]$/');
                 }
             }
             if (!empty($role['settings'][Scalr_Role_Behavior::ROLE_BASE_CUSTOM_TAGS]) && PlatformFactory::isOpenstack($role['platform'])) {
                 $reservedBaseCustomTags = ['scalr-meta', 'farmid', 'role', 'httpproto', 'region', 'hash', 'realrolename', 'szr_key', 'serverid', 'p2p_producer_endpoint', 'queryenv_url', 'behaviors', 'farm_roleid', 'roleid', 'env_id', 'platform', 'server_index', 'cloud_server_id', 'cloud_location_zone', 'owner_email'];
                 $baseCustomTags = @explode("\n", $role['settings'][Scalr_Role_Behavior::ROLE_BASE_CUSTOM_TAGS]);
                 foreach ((array) $baseCustomTags as $tag) {
                     $tag = trim($tag);
                     $tagChunks = explode("=", $tag);
                     if (in_array(trim($tagChunks[0]), $reservedBaseCustomTags)) {
                         $this->setBuildError(Scalr_Role_Behavior::ROLE_BASE_CUSTOM_TAGS, "Avoid using Scalr-reserved metadata names.", $role['farm_role_id']);
                     }
                 }
             }
             if (!empty($role['settings'][Scalr_Role_Behavior::ROLE_BASE_HOSTNAME_FORMAT])) {
                 if (!preg_match('/^[\\w\\{\\}\\.-]+$/', $role['settings'][Scalr_Role_Behavior::ROLE_BASE_HOSTNAME_FORMAT])) {
                     $this->setBuildError(Scalr_Role_Behavior::ROLE_BASE_HOSTNAME_FORMAT, "server hostname format for role'{$dbRole->name}' should contain only [a-z0-9-] chars. First char should not be hypen.", $role['farm_role_id']);
                 }
             }
             if (!empty($role['settings'][Entity\FarmRoleSetting::DNS_CREATE_RECORDS])) {
                 if ($role['settings'][Entity\FarmRoleSetting::DNS_EXT_RECORD_ALIAS]) {
                     if (!preg_match('/^[\\w\\{\\}\\.-]+$/', $role['settings'][Entity\FarmRoleSetting::DNS_EXT_RECORD_ALIAS])) {
                         $this->setBuildError(Entity\FarmRoleSetting::DNS_EXT_RECORD_ALIAS, "ext- record alias for role '{$dbRole->name}' should contain only [A-Za-z0-9-] chars. First and last char should not be hypen.", $role['farm_role_id']);
                     }
                 }
                 if ($role['settings'][Entity\FarmRoleSetting::DNS_INT_RECORD_ALIAS]) {
                     if (!preg_match('/^[\\w\\{\\}\\.-]+$/', $role['settings'][Entity\FarmRoleSetting::DNS_INT_RECORD_ALIAS])) {
                         $this->setBuildError(Entity\FarmRoleSetting::DNS_INT_RECORD_ALIAS, "int- record alias for role '{$dbRole->name}' should contain only [A-Za-z0-9-] chars. First and last char should not by hypen.", $role['farm_role_id']);
                     }
                 }
             }
             // Validate Global variables
             if (!strstr($role['farm_role_id'], 'virtual_')) {
                 $farmRole = DBFarmRole::LoadByID($role['farm_role_id']);
             } else {
                 $farmRole = null;
                 if ($dbRole->isDeprecated == 1) {
                     $this->setBuildError('roleId', 'This role has been deprecated and cannot be added', $role['farm_role_id']);
                 }
                 if (!empty($envs = $dbRole->__getNewRoleObject()->getAllowedEnvironments())) {
                     if (!in_array($this->getEnvironmentId(), $envs)) {
                         $this->setBuildError('roleId', "You don't have access to this role", $role['farm_role_id']);
                     }
                 }
             }
             if (isset($role['storages']['configs'])) {
                 // TODO: refactor, get rid of using DBFarmRole in constructor
                 $fr = $farmRole ? $farmRole : new DBFarmRole(0);
                 foreach ($fr->getStorage()->validateConfigs($role['storages']['configs']) as $index => $message) {
                     $this->setBuildError('storages', ['message' => $message, 'invalidIndex' => $index], $role['farm_role_id']);
                     break;
                 }
             }
             $result = $farmRoleVariables->validateValues(is_array($role['variables']) ? $role['variables'] : [], $dbRole->id, $farmId, $farmRole ? $farmRole->ID : 0);
             if ($result !== TRUE) {
                 $this->setBuildError('variables', $result, $role['farm_role_id']);
             }
         }
     }
     if ($farmSettings['vpc_id']) {
         if (!$hasVpcRouter && $vpcRouterRequired) {
             $this->setBuildError(Entity\FarmRoleSetting::AWS_VPC_SUBNET_ID, 'You must select a VPC Router for Farm Roles launched in a Private VPC Subnet', $vpcRouterRequired);
         }
     }
     if ($this->getContainer()->analytics->enabled) {
         if ($farmSettings['projectId']) {
             $project = $this->getContainer()->analytics->projects->get($farmSettings['projectId']);
             if (!$project) {
                 $this->setBuildError('projectId', 'Project not found', null);
             } else {
                 if ($project->ccId != $this->getEnvironment()->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID)) {
                     $this->setBuildError('projectId', 'Invalid project identifier. Project should correspond to the Environment\'s cost center.', null);
                 }
             }
         } else {
             $this->setBuildError('projectId', 'Project field is required', null);
         }
     }
     return $this->errors['error_count'] == 0 ? true : false;
 }
Beispiel #10
0
 public function extendMessage(Scalr_Messaging_Msg $message, DBServer $dbServer)
 {
     switch (get_class($message)) {
         case "Scalr_Messaging_Msg_HostInitResponse":
             try {
                 if ($dbServer->farmRoleId) {
                     $appId = $dbServer->GetFarmRoleObject()->GetSetting(self::ROLE_DM_APPLICATION_ID);
                     if (!$message->deploy && $appId) {
                         $application = Scalr_Dm_Application::init()->loadById($appId);
                         $deploymentTask = Scalr_Dm_DeploymentTask::init();
                         $deploymentTask->create($dbServer->farmRoleId, $appId, $dbServer->serverId, Scalr_Dm_DeploymentTask::TYPE_AUTO, $dbServer->GetFarmRoleObject()->GetSetting(self::ROLE_DM_REMOTE_PATH), $dbServer->envId, Scalr_Dm_DeploymentTask::STATUS_DEPLOYING);
                         $msg = $deploymentTask->getDeployMessage();
                         $message->deploy = $msg;
                     }
                 }
             } catch (Exception $e) {
                 $this->logger->error(new FarmLogMessage($dbServer->farmId, "Cannot init deployment: {$e->getMessage()}"));
             }
             break;
     }
     return $message;
 }