public function xGetDetailsAction() { $amazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); $rInstances = $amazonEC2Client->DescribeReservedInstances(); $rInstances = $rInstances->reservedInstancesSet->item; if ($rInstances instanceof stdClass) { $rInstances = array($rInstances); } $result = array(); foreach ($rInstances as $rInstance) { if ($rInstance->state == 'active') { $result[$rInstance->availabilityZone][$rInstance->instanceType]['rCount'] += $rInstance->instanceCount; } } $servers = $this->db->Execute("SELECT servers.server_id FROM `servers` INNER JOIN server_properties ON server_properties.server_id = servers.server_id \r\n\t\t\tWHERE status=? AND name='ec2.region' AND env_id=? AND value=?", array(SERVER_STATUS::RUNNING, $this->getEnvironmentId(), $this->getParam('cloudLocation'))); while ($server = $servers->FetchRow()) { $dbServer = DBServer::LoadByID($server['server_id']); $result[$dbServer->GetProperty(EC2_SERVER_PROPERTIES::AVAIL_ZONE)][$dbServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_TYPE)]['iCount']++; } $retval = array(); foreach ($result as $availZone => $i) { foreach ($i as $instanceType => $data) { $retval[] = array('availZone' => $availZone, 'instanceType' => $instanceType, 'scalrInstances' => (int) $data['iCount'], 'reservedInstances' => (int) $data['rCount']); } } $this->response->data(array('success' => true, 'data' => $retval)); }
public function xRemoveAction() { $this->request->defineParams(array('volumeId' => array('type' => 'json'), 'cloudLocation')); $amazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); foreach ($this->getParam('volumeId') as $volumeId) { $amazonEC2Client->DeleteVolume($volumeId); $this->db->Execute("DELETE FROM ec2_ebs WHERE volume_id=?", array($volumeId)); } $this->response->success('Volume(s) successfully removed'); }
public function xListEipsAction() { $amazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); // Rows $aws_response = $amazonEC2Client->DescribeAddresses(); $rowz = $aws_response->addressesSet->item; if ($rowz instanceof stdClass) { $rowz = array($rowz); } foreach ($rowz as &$pv) { $item = array('ipaddress' => $pv->publicIp, 'instance_id' => $pv->instanceId); $info = $this->db->GetRow("SELECT * FROM elastic_ips WHERE ipaddress=?", array($pv->publicIp)); if ($info) { $item['farm_id'] = $info['farmid']; $item['farm_roleid'] = $info['farm_roleid']; $item['server_id'] = $info['server_id']; $item['indb'] = true; $item['server_index'] = $info['instance_index']; //WORKAROUND: EIPS not imported correclty from 1.2 to 2.0 if (!$item['server_id'] && $info['state'] == 1) { try { $DBServer = DBServer::LoadByPropertyValue(EC2_SERVER_PROPERTIES::INSTANCE_ID, $item['instance_id']); $item['server_id'] = $DBServer->serverId; } catch (Exception $e) { } } if ($item['farm_roleid']) { try { $DBFarmRole = DBFarmRole::LoadByID($item['farm_roleid']); $item['role_name'] = $DBFarmRole->GetRoleObject()->name; $item['farm_name'] = $DBFarmRole->GetFarmObject()->Name; } catch (Exception $e) { } } } else { try { $DBServer = DBServer::LoadByPropertyValue(EC2_SERVER_PROPERTIES::INSTANCE_ID, $pv->instanceId); $item['server_id'] = $DBServer->serverId; $item['farm_id'] = $DBServer->farmId; } catch (Exception $e) { } } $pv = $item; } $response = $this->buildResponseFromData($rowz); $this->response->data($response); }
public function xGetSnapshotsAction() { $amazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); $response = $amazonEC2Client->DescribeSnapshots(); if ($response->snapshotSet->item instanceof stdClass) { $response->snapshotSet->item = array($response->snapshotSet->item); } $data = array(); foreach ($response->snapshotSet->item as $pk => $pv) { if ($pv->ownerId != $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::ACCOUNT_ID)) { continue; } if ($pv->status == 'completed') { $data[] = array('snapid' => (string) $pv->snapshotId, 'createdat' => Scalr_Util_DateTime::convertTz($pv->startTime), 'size' => (string) $pv->volumeSize); } } $this->response->data(array('data' => $data)); }
public static function farmUpdateRoleSettings(DBFarmRole $DBFarmRole, $oldSettings, $newSettings) { $db = Core::GetDBInstance(); $DBFarm = $DBFarmRole->GetFarmObject(); if (!$oldSettings[DBFarmRole::SETTING_AWS_USE_ELASIC_IPS] && $newSettings[DBFarmRole::SETTING_AWS_USE_ELASIC_IPS]) { $servers = $DBFarmRole->GetServersByFilter(array('status' => SERVER_STATUS::RUNNING)); if (count($servers) == 0) { return; } $AmazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($DBFarmRole->CloudLocation, $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); foreach ($servers as $DBServer) { $address = $AmazonEC2Client->AllocateAddress(); $db->Execute("INSERT INTO elastic_ips SET env_id=?, farmid=?, farm_roleid=?, ipaddress=?, state='0', instance_id='', clientid=?, instance_index=?", array($DBServer->envId, $DBServer->farmId, $DBServer->farmRoleId, $address->publicIp, $DBServer->clientId, $DBServer->index)); Logger::getLogger(__CLASS__)->info(sprintf(_("Allocated new IP: %s"), $address->publicIp)); // Waiting... Logger::getLogger(__CLASS__)->debug(_("Waiting 5 seconds...")); sleep(5); $assign_retries = 1; while (true) { try { // Associate elastic ip address with instance $AmazonEC2Client->AssociateAddress($DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID), $address->publicIp); } catch (Exception $e) { if (!stristr($e->getMessage(), "does not belong to you") || $assign_retries == 3) { throw new Exception($e->getMessage()); } else { // Waiting... Logger::getLogger(__CLASS__)->debug(_("Waiting 2 seconds...")); sleep(2); $assign_retries++; continue; } } break; } Logger::getLogger(__CLASS__)->info(sprintf(_("IP: %s assigned to instance '%s'"), $address->publicIp, $DBServer->serverId)); // Update leastic IPs table $db->Execute("UPDATE elastic_ips SET state='1', server_id=? WHERE ipaddress=?", array($DBServer->serverId, $address->publicIp)); Scalr::FireEvent($DBFarmRole->FarmID, new IPAddressChangedEvent($DBServer, $address->publicIp)); } } }
public function xListSnapshotsAction() { $this->request->defineParams(array('sort' => array('type' => 'json', 'default' => array('property' => 'snapshotId', 'direction' => 'ASC')), 'showPublicSnapshots', 'cloudLocation', 'volumeId', 'snapshotId')); $amazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); // Rows $aws_response = $amazonEC2Client->DescribeSnapshots(); $rowz = $aws_response->snapshotSet->item; if ($rowz instanceof stdClass) { $rowz = array($rowz); } $snaps = array(); foreach ($rowz as $pk => $pv) { if ($this->getParam('volumeId') && $pv->volumeId != $this->getParam('volumeId')) { continue; } if ($this->getParam('snapshotId') && $pv->snapshotId != $this->getParam('snapshotId')) { continue; } $item = (array) $pv; if ($pv->ownerId != $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::ACCOUNT_ID)) { $item['comment'] = $pv->description; $item['owner'] = $pv->ownerId; if (!$this->getParam('showPublicSnapshots')) { continue; } } else { $comment = $this->db->GetOne("SELECT comment FROM ebs_snaps_info WHERE snapid=?", array($pv->snapshotId)); $item['comment'] = $comment ? $comment : $pv->description; $item['owner'] = 'Me'; } $item['progress'] = (int) preg_replace("/[^0-9]+/", "", $item['progress']); unset($item['description']); $snaps[] = $item; } $response = $this->buildResponseFromData($snaps, array('snapshotId', 'volumeId', 'comment', 'owner')); foreach ($response['data'] as &$row) { $row['startTime'] = Scalr_Util_DateTime::convertTz($row['startTime']); } $this->response->data($response); }
public function regenerateAction() { $this->request->defineParams(array('sshKeyId' => array('type' => 'int'))); $sshKey = Scalr_SshKey::init()->loadById($this->getParam('sshKeyId')); $this->user->getPermissions()->validate($sshKey); if ($sshKey->type == Scalr_SshKey::TYPE_GLOBAL) { if ($sshKey->platform == 'ec2') { $AmazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($sshKey->cloudLocation, $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); $AmazonEC2Client->DeleteKeyPair($sshKey->cloudKeyName); $result = $AmazonEC2Client->CreateKeyPair($sshKey->cloudKeyName); if ($result->keyMaterial) { $sshKey->setPrivate($result->keyMaterial); $pubKey = $sshKey->generatePublicKey(); if (!$pubKey) { throw new Exception("Keypair generation failed"); } $oldKey = $sshKey->getPublic(); $sshKey->setPublic($pubKey); $sshKey->save(); $dbFarm = DBFarm::LoadByID($sshKey->farmId); $servers = $dbFarm->GetServersByFilter(array('platform' => SERVER_PLATFORMS::EC2, 'status' => array(SERVER_STATUS::RUNNING, SERVER_STATUS::INIT, SERVER_STATUS::PENDING))); foreach ($servers as $dbServer) { if ($dbServer->GetCloudLocation() == $sshKey->cloudLocation) { $msg = new Scalr_Messaging_Msg_UpdateSshAuthorizedKeys(array($pubKey), array($oldKey)); $dbServer->SendMessage($msg); } } $this->response->success(); } } else { //TODO: } } else { //TODO: } }
public function xListVolumesAction() { $this->request->defineParams(array('sort' => array('type' => 'json', 'default' => array('property' => 'volumeId', 'direction' => 'DESC')), 'volumeId')); $amazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); // Rows $aws_response = $amazonEC2Client->DescribeVolumes(); $rowz = $aws_response->volumeSet->item; if ($rowz instanceof stdClass) { $rowz = array($rowz); } $vols = array(); foreach ($rowz as $pk => $pv) { if ($pv->attachmentSet && $pv->attachmentSet->item) { $pv->attachmentSet = $pv->attachmentSet->item; } if ($this->getParam('volumeId') && $this->getParam('volumeId') != $pv->volumeId) { continue; } $item = array('volumeId' => $pv->volumeId, 'size' => $pv->size, 'snapshotId' => $pv->snapshotId, 'availZone' => $pv->availabilityZone, 'status' => $pv->status, 'attachmentStatus' => $pv->attachmentSet->status, 'device' => $pv->attachmentSet->device, 'instanceId' => $pv->attachmentSet->instanceId); $item['autoSnaps'] = $this->db->GetOne("SELECT id FROM autosnap_settings WHERE objectid=? AND object_type=?", array($pv->volumeId, AUTOSNAPSHOT_TYPE::EBSSnap)) ? true : false; $DBEBSVolume = false; try { $DBEBSVolume = DBEBSVolume::loadByVolumeId($pv->volumeId); //$sort_key = "{$DBEBSVolume->farmId}_{$DBEBSVolume->farmRoleId}_{$pv->volumeId}"; $item['farmId'] = $DBEBSVolume->farmId; $item['farmRoleId'] = $DBEBSVolume->farmRoleId; $item['serverIndex'] = $DBEBSVolume->serverIndex; $item['serverId'] = $DBEBSVolume->serverId; $item['mountStatus'] = $DBEBSVolume->mountStatus; $item['farmName'] = DBFarm::LoadByID($DBEBSVolume->farmId)->Name; $item['roleName'] = DBFarmRole::LoadByID($DBEBSVolume->farmRoleId)->GetRoleObject()->name; $item['autoAttach'] = true; } catch (Exception $e) { } if (!$DBEBSVolume && $item['instanceId']) { try { $dbServer = DBServer::LoadByPropertyValue(EC2_SERVER_PROPERTIES::INSTANCE_ID, $item['instanceId']); $item['farmId'] = $dbServer->farmId; $item['farmRoleId'] = $dbServer->farmRoleId; $item['serverIndex'] = $dbServer->index; $item['serverId'] = $dbServer->serverId; $item['farmName'] = $dbServer->GetFarmObject()->Name; $item['mountStatus'] = false; $item['roleName'] = $dbServer->GetFarmRoleObject()->GetRoleObject()->name; } catch (Exception $e) { } } $vols[] = $item; } $response = $this->buildResponseFromData($vols, array('instanceId', 'volumeId', 'snapshotId', 'farmId', 'farmRoleId', 'availZone')); $this->response->data($response); }
public function restoreAction() { $amazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); $response = $amazonEC2Client->DescribeAvailabilityZones(); if ($response->availabilityZoneInfo->item instanceof stdClass) { $response->availabilityZoneInfo->item = array($response->availabilityZoneInfo->item); } foreach ($response->availabilityZoneInfo->item as $zone) { if (stristr($zone->zoneState, 'available')) { $zones[] = array('id' => (string) $zone->zoneName, 'name' => (string) $zone->zoneName); } } $this->response->page('ui/tools/aws/rds/instances/restore.js', array('zones' => $zones)); }
public function StartThread($volume) { $db = Core::GetDBInstance(null, true); $DBEBSVolume = DBEBSVolume::loadById($volume['id']); $EC2Client = Scalr_Service_Cloud_Aws::newEc2($DBEBSVolume->ec2Region, $DBEBSVolume->getEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $DBEBSVolume->getEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); if ($DBEBSVolume->volumeId) { try { $result = $EC2Client->DescribeVolumes($DBEBSVolume->volumeId); $volumeinfo = $result->volumeSet->item; } catch (Exception $e) { if (stristr($e->getMessage(), "does not exist")) { $DBEBSVolume->delete(); exit; } else { $this->logger->error("Cannot get EBS volume information: {$e->getMessage()}. Database ID: {$DBEBSVolume->id}"); } } } switch ($DBEBSVolume->attachmentStatus) { case EC2_EBS_ATTACH_STATUS::DELETING: if ($DBEBSVolume->volumeId) { try { $EC2Client->DeleteVolume($DBEBSVolume->volumeId); $removeFromDb = true; } catch (Exception $e) { if (stristr($e->getMessage(), "does not exist")) { $removeFromDb = true; } else { $this->logger->error("Cannot remove volume: {$e->getMessage()}. Database ID: {$DBEBSVolume->id}"); } } } else { $removeFromDb = true; } if ($removeFromDb) { $DBEBSVolume->delete(); } break; case EC2_EBS_ATTACH_STATUS::ATTACHING: switch ($volumeinfo->status) { case AMAZON_EBS_STATE::IN_USE: $volumeInstanceId = $volumeinfo->attachmentSet->item->instanceId; $DBServer = DBServer::LoadByID($DBEBSVolume->serverId); if ($volumeInstanceId == $DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID)) { $DBEBSVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::ATTACHED; } else { $this->logger->warn(sprintf(_("Volume #%s should be attached to server %s (%s), but it already attached to instance %s. Re-attaching..."), $DBEBSVolume->volumeId, $DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID), $DBServer->serverId, $volumeInstanceId)); try { $DetachVolumeType = new DetachVolumeType($DBEBSVolume->volumeId, $volumeInstanceId, $DBEBSVolume->deviceName, true); $EC2Client->DetachVolume($DetachVolumeType); } catch (Exception $e) { } } $DBEBSVolume->save(); break; case AMAZON_EBS_STATE::AVAILABLE: $attach_volume = true; break; case AMAZON_EBS_STATE::ATTACHING: // NOTHING TO DO; break; default: $this->logger->error("Cannot attach volume to server {$DBServer->serverId}. Volume status: {$volumeinfo->status}. Volume Database ID: {$DBEBSVolume->id}. Volume ID: {$DBEBSVolume->volumeId} (" . serialize($volumeinfo) . ")"); break; } break; case EC2_EBS_ATTACH_STATUS::CREATING: if (!$DBEBSVolume->volumeId) { if ($DBEBSVolume->ec2AvailZone == 'x-scalr-diff' || stristr($DBEBSVolume->ec2AvailZone, "x-scalr-custom")) { if ($DBEBSVolume->serverId) { $DBEBSVolume->ec2AvailZone = DBServer::LoadByID($DBEBSVolume->serverId)->GetProperty(EC2_SERVER_PROPERTIES::AVAIL_ZONE); } else { $DBEBSVolume->delete(); } } $CreateVolumeType = new CreateVolumeType($DBEBSVolume->size, $DBEBSVolume->snapId ? $DBEBSVolume->snapId : "", $DBEBSVolume->ec2AvailZone); try { $result = $EC2Client->CreateVolume($CreateVolumeType); if ($result->volumeId) { $DBEBSVolume->volumeId = $result->volumeId; $DBEBSVolume->save(); $this->logger->info("Created new volume: {$DBEBSVolume->volumeId}. Database ID: {$DBEBSVolume->id}"); } else { $this->logger->error("Cannot create volume. Database ID: {$DBEBSVolume->id}"); exit; } } catch (Exception $e) { if (stristr($e->getMessage(), "must be at least snapshot size")) { @preg_match_all("/(([0-9]+)GiB)/sim", $e->getMessage(), $matches); if ($matches[2][1] > 1) { $DBEBSVolume->size = $matches[2][1]; $DBEBSVolume->save(); } } $this->logger->error("Cannot create volume: {$e->getMessage()}. Database ID: {$DBEBSVolume->id}"); exit; } } else { if ($volumeinfo && $DBEBSVolume->volumeId) { if ($volumeinfo->status == AMAZON_EBS_STATE::AVAILABLE) { if (!$DBEBSVolume->serverId) { $DBEBSVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::AVAILABLE; $DBEBSVolume->save(); } else { $attach_volume = true; } } } } break; } switch ($DBEBSVolume->mountStatus) { case EC2_EBS_MOUNT_STATUS::AWAITING_ATTACHMENT: if ($DBEBSVolume->attachmentStatus == EC2_EBS_ATTACH_STATUS::ATTACHED) { $DBEBSVolume->mountStatus = EC2_EBS_MOUNT_STATUS::MOUNTING; $DBEBSVolume->save(); $DBServer = DBServer::LoadByID($DBEBSVolume->serverId); $DBServer->SendMessage(new Scalr_Messaging_Msg_MountPointsReconfigure()); } break; case EC2_EBS_MOUNT_STATUS::MOUNTING: //NOTHING TO DO break; } if ($attach_volume) { try { $DBServer = DBServer::LoadByID($DBEBSVolume->serverId); if ($DBServer->status != SERVER_STATUS::RUNNING && $DBServer->IsSupported("0.7.36")) { $DBEBSVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::ATTACHING; $DBEBSVolume->save(); $this->logger->fatal("Szr verison > 0.7.36. Status: {$DBServer->status}. VolumeID: {$DBEBSVolume->volumeId}"); return; } } catch (ServerNotFoundException $e) { if ($DBEBSVolume->volumeId) { $DBEBSVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::AVAILABLE; $DBEBSVolume->mountStatus = EC2_EBS_MOUNT_STATUS::NOT_MOUNTED; $DBEBSVolume->save(); } } if ($DBServer) { //NOT supported if ($DBServer->GetOsFamily() == 'windows') { return; } try { $attachVolumeType = new AttachVolumeType($DBEBSVolume->volumeId, $DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID), $DBServer->GetFreeDeviceName()); $result = $EC2Client->AttachVolume($attachVolumeType); } catch (Exception $e) { if (!stristr($e->getMessage(), "is not in the same availability zone as instance") && !stristr($e->getMessage(), "Cannot get a list of used disk devices")) { $this->logger->fatal("Cannot attach volume: {$e->getMessage()}"); } else { $this->logger->info("Cannot attach volume: {$e->getMessage()}"); } } if ($result->status == AMAZON_EBS_STATE::IN_USE || $result->status == AMAZON_EBS_STATE::ATTACHING) { $DBEBSVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::ATTACHING; $DBEBSVolume->deviceName = $attachVolumeType->device; $DBEBSVolume->save(); } else { $this->logger->warn("Cannot attach volume: volume status: {$result->status} ({$volumeinfo->status}). Database ID: {$DBEBSVolume->id}. Volume ID: {$DBEBSVolume->volumeId}"); } } } }
public function LaunchServer(DBServer $DBServer, Scalr_Server_LaunchOptions $launchOptions = null) { $RunInstancesType = new RunInstancesType(); $RunInstancesType->ConfigureRootPartition(); if (!$launchOptions) { $launchOptions = new Scalr_Server_LaunchOptions(); $DBRole = DBRole::loadById($DBServer->roleId); // Set Cloudwatch monitoring $RunInstancesType->SetCloudWatchMonitoring($DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_AWS_ENABLE_CW_MONITORING)); $launchOptions->architecture = $DBRole->architecture; $launchOptions->imageId = $DBRole->getImageId(SERVER_PLATFORMS::EC2, $DBServer->GetFarmRoleObject()->CloudLocation); $launchOptions->cloudLocation = $DBServer->GetFarmRoleObject()->CloudLocation; $akiId = $DBServer->GetProperty(EC2_SERVER_PROPERTIES::AKIID); if (!$akiId) { $akiId = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_AWS_AKI_ID); } if ($akiId) { $RunInstancesType->kernelId = $akiId; } $ariId = $DBServer->GetProperty(EC2_SERVER_PROPERTIES::ARIID); if (!$ariId) { $ariId = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_AWS_ARI_ID); } if ($ariId) { $RunInstancesType->ramdiskId = $ariId; } $i_type = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_AWS_INSTANCE_TYPE); if (!$i_type) { $DBRole = DBRole::loadById($DBServer->roleId); $i_type = $DBRole->getProperty(EC2_SERVER_PROPERTIES::INSTANCE_TYPE); } $launchOptions->serverType = $i_type; foreach ($DBServer->GetCloudUserData() as $k => $v) { $u_data .= "{$k}={$v};"; } $RunInstancesType->SetUserData(trim($u_data, ";")); $vpcPrivateIp = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_AWS_VPC_PRIVATE_IP); $vpcSubnetId = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_AWS_VPC_SUBNET_ID); if ($vpcSubnetId) { $RunInstancesType->subnetId = $vpcSubnetId; if ($vpcPrivateIp) { $RunInstancesType->privateIpAddress = $vpcPrivateIp; } } } else { $RunInstancesType->SetUserData(trim($launchOptions->userData)); } $DBServer->SetProperty(SERVER_PROPERTIES::ARCHITECTURE, $launchOptions->architecture); $EC2Client = Scalr_Service_Cloud_Aws::newEc2($launchOptions->cloudLocation, $DBServer->GetEnvironmentObject()->getPlatformConfigValue(self::PRIVATE_KEY), $DBServer->GetEnvironmentObject()->getPlatformConfigValue(self::CERTIFICATE)); // Set AMI, AKI and ARI ids $RunInstancesType->imageId = $launchOptions->imageId; if (!$RunInstancesType->subnetId) { // Set Security groups foreach ($this->GetServerSecurityGroupsList($DBServer, $EC2Client) as $sgroup) { $RunInstancesType->AddSecurityGroup($sgroup); } } $RunInstancesType->minCount = 1; $RunInstancesType->maxCount = 1; // Set availability zone if (!$launchOptions->availZone) { $avail_zone = $this->GetServerAvailZone($DBServer, $EC2Client, $launchOptions); if ($avail_zone) { $RunInstancesType->SetAvailabilityZone($avail_zone); } } else { $RunInstancesType->SetAvailabilityZone($launchOptions->availZone); } // Set instance type $RunInstancesType->instanceType = $launchOptions->serverType; if (in_array($RunInstancesType->instanceType, array('cc1.4xlarge', 'cg1.4xlarge', 'cc2.8xlarge'))) { $placementGroup = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_AWS_CLUSTER_PG); if (!$placementGroup) { $placementGroup = "scalr-role-{$DBServer->farmRoleId}"; if (!$EC2Client->CreatePlacementGroup($placementGroup)) { throw new Exception(sprintf(_("Cannot launch new instance. Unable to create placement group: %s"), $result->faultstring)); } $DBServer->GetFarmRoleObject()->SetSetting(DBFarmRole::SETTING_AWS_CLUSTER_PG, $placementGroup); } $RunInstancesType->SetPlacementGroup($placementGroup); } // Set additional info $RunInstancesType->additionalInfo = ""; ///// if ($DBServer->status == SERVER_STATUS::TEMPORARY) { $keyName = "SCALR-ROLESBUILDER"; $sshKey = Scalr_Model::init(Scalr_Model::SSH_KEY); if (!$sshKey->loadGlobalByName($keyName, $launchOptions->cloudLocation, $DBServer->envId)) { $result = $EC2Client->CreateKeyPair($keyName); if ($result->keyMaterial) { $sshKey->farmId = 0; $sshKey->clientId = $DBServer->clientId; $sshKey->envId = $DBServer->envId; $sshKey->type = Scalr_SshKey::TYPE_GLOBAL; $sshKey->cloudLocation = $launchOptions->cloudLocation; $sshKey->cloudKeyName = $keyName; $sshKey->platform = SERVER_PLATFORMS::EC2; $sshKey->setPrivate($result->keyMaterial); $sshKey->setPublic($sshKey->generatePublicKey()); $sshKey->save(); } } } else { $sshKey = Scalr_Model::init(Scalr_Model::SSH_KEY)->loadGlobalByFarmId($DBServer->farmId, $DBServer->GetProperty(EC2_SERVER_PROPERTIES::REGION)); $keyName = $sshKey->cloudKeyName; } ///// $RunInstancesType->keyName = $keyName; try { $result = $EC2Client->RunInstances($RunInstancesType); } catch (Exception $e) { if (stristr($e->getMessage(), "key pair") && stristr($e->getMessage(), "does not exist")) { $result = $EC2Client->CreateKeyPair($keyName); if ($result->keyMaterial) { $sshKey->setPrivate($result->keyMaterial); $sshKey->setPublic($sshKey->generatePublicKey()); $sshKey->save(); } //Your requested instance type (m2.2xlarge) is not supported in your requested Availability Zone (us-east-1a). Please retry your request by not specifying an Availability Zone or choosing us-east-1c, us-east-1b, us-east-1 } else { if (stristr($e->getMessage(), "The requested Availability Zone is no longer supported") || stristr($e->getMessage(), "is not supported in your requested Availability Zone")) { $availZone = $RunInstancesType->placement->availabilityZone; $DBServer->GetEnvironmentObject()->setPlatformConfig(array("aws.{$launchOptions->cloudLocation}.{$availZone}.unavailable" => time()), false); throw $e; } else { throw $e; } } } if ($result->instancesSet) { $DBServer->SetProperty(EC2_SERVER_PROPERTIES::AVAIL_ZONE, (string) $result->instancesSet->item->placement->availabilityZone); $DBServer->SetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID, (string) $result->instancesSet->item->instanceId); $DBServer->SetProperty(EC2_SERVER_PROPERTIES::INSTANCE_TYPE, $RunInstancesType->instanceType); $DBServer->SetProperty(EC2_SERVER_PROPERTIES::AMIID, $RunInstancesType->imageId); $DBServer->SetProperty(EC2_SERVER_PROPERTIES::REGION, $launchOptions->cloudLocation); try { if ($DBServer->farmId != 0) { $CreateTagsType = new CreateTagsType(array((string) $result->instancesSet->item->instanceId), array("scalr-farm-id" => $DBServer->farmId, "scalr-farm-name" => $DBServer->GetFarmObject()->Name, "scalr-farm-role-id" => $DBServer->farmRoleId, "scalr-role-name" => $DBServer->GetFarmRoleObject()->GetRoleObject()->name, "scalr-server-id" => $DBServer->serverId)); $EC2Client->CreateTags($CreateTagsType); } } catch (Exception $e) { Logger::getLogger('EC2')->warn("Cannot add tags to server: {$e->getMessage()}"); } return $DBServer; } else { throw new Exception(sprintf(_("Cannot launch new instance. %s"), serialize($result))); } }
private function getPlatformClient() { if (!$this->getParam('platform')) { throw new Exception('Platform should be specified'); } switch ($this->getParam('platform')) { case SERVER_PLATFORMS::EC2: return Scalr_Service_Cloud_Aws::newEc2($this->getParam('cloudLocation'), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $this->getEnvironment()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); break; default: throw new Exception("Platfrom not suppored"); break; } }
public function xSaveEc2Action() { $pars = array(); $enabled = false; if ($this->getParam('ec2_is_enabled')) { $enabled = true; $pars[Modules_Platforms_Ec2::ACCOUNT_ID] = $this->checkVar(Modules_Platforms_Ec2::ACCOUNT_ID, 'string', "AWS Account Number required"); if (!is_numeric($pars[Modules_Platforms_Ec2::ACCOUNT_ID]) || strlen($pars[Modules_Platforms_Ec2::ACCOUNT_ID]) != 12) { //$err[Modules_Platforms_Ec2::ACCOUNT_ID] = _("AWS numeric account ID required (See <a href='/faq.html'>FAQ</a> for info on where to get it)."); $this->checkVarError[Modules_Platforms_Ec2::ACCOUNT_ID] = _("AWS Account Number should be numeric"); } else { $pars[Modules_Platforms_Ec2::ACCOUNT_ID] = preg_replace("/[^0-9]+/", "", $pars[Modules_Platforms_Ec2::ACCOUNT_ID]); } $pars[Modules_Platforms_Ec2::ACCESS_KEY] = $this->checkVar(Modules_Platforms_Ec2::ACCESS_KEY, 'string', "AWS Access Key required"); $pars[Modules_Platforms_Ec2::SECRET_KEY] = $this->checkVar(Modules_Platforms_Ec2::SECRET_KEY, 'password', "AWS Access Key required"); $pars[Modules_Platforms_Ec2::PRIVATE_KEY] = trim($this->checkVar(Modules_Platforms_Ec2::PRIVATE_KEY, 'file', "AWS x.509 Private Key required")); $pars[Modules_Platforms_Ec2::CERTIFICATE] = trim($this->checkVar(Modules_Platforms_Ec2::CERTIFICATE, 'file', "AWS x.509 Certificate required")); // the same as EC2 $pars[Modules_Platforms_Rds::ACCOUNT_ID] = $pars[Modules_Platforms_Ec2::ACCOUNT_ID]; $pars[Modules_Platforms_Rds::ACCESS_KEY] = $pars[Modules_Platforms_Ec2::ACCESS_KEY]; $pars[Modules_Platforms_Rds::SECRET_KEY] = $pars[Modules_Platforms_Ec2::SECRET_KEY]; $pars[Modules_Platforms_Rds::PRIVATE_KEY] = $pars[Modules_Platforms_Ec2::PRIVATE_KEY]; $pars[Modules_Platforms_Rds::CERTIFICATE] = $pars[Modules_Platforms_Ec2::CERTIFICATE]; if (!count($this->checkVarError)) { if ($pars[Modules_Platforms_Ec2::ACCOUNT_ID] != $this->env->getPlatformConfigValue(Modules_Platforms_Ec2::ACCOUNT_ID) or $pars[Modules_Platforms_Ec2::ACCESS_KEY] != $this->env->getPlatformConfigValue(Modules_Platforms_Ec2::ACCESS_KEY) or $pars[Modules_Platforms_Ec2::SECRET_KEY] != $this->env->getPlatformConfigValue(Modules_Platforms_Ec2::SECRET_KEY) or $pars[Modules_Platforms_Ec2::PRIVATE_KEY] != $this->env->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY) or $pars[Modules_Platforms_Ec2::CERTIFICATE] != $this->env->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)) { try { $AmazonEC2Client = Scalr_Service_Cloud_Aws::newEc2('us-east-1', $pars[Modules_Platforms_Ec2::PRIVATE_KEY], $pars[Modules_Platforms_Ec2::CERTIFICATE]); $AmazonEC2Client->describeInstances(); } catch (Exception $e) { throw new Exception(_("Incorrect format of X.509 certificate or private key. Make sure that you are using files downloaded from AWS profile. ({$e->getMessage()})")); } try { $AmazonS3 = new AmazonS3($pars[Modules_Platforms_Ec2::ACCESS_KEY], $pars[Modules_Platforms_Ec2::SECRET_KEY]); $buckets = $AmazonS3->ListBuckets(); } catch (Exception $e) { throw new Exception(sprintf(_("Failed to verify your EC2 access key and secret key: %s"), $e->getMessage())); } } } else { $this->response->failure(); $this->response->data(array('errors' => $this->checkVarError)); return; } } $this->db->BeginTrans(); try { $this->env->enablePlatform(SERVER_PLATFORMS::EC2, $enabled); $this->env->enablePlatform(SERVER_PLATFORMS::RDS, $enabled); if ($enabled) { $this->env->setPlatformConfig($pars); } if (!$this->user->getAccount()->getSetting(Scalr_Account::SETTING_DATE_ENV_CONFIGURED)) { $this->user->getAccount()->setSetting(Scalr_Account::SETTING_DATE_ENV_CONFIGURED, time()); } if ($this->user->getAccount()->getSetting(Scalr_Account::SETTING_IS_TRIAL) == 1) { if ($this->db->GetOne("SELECT COUNT(*) FROM farms WHERE clientid = ?", array($this->user->getAccountId())) == 0) { //Create demo farm try { $dbFarm = DBFarm::LoadByID(9670); // LAMP-PROTOTYPE $dbFarm->cloneFarm('My First LAMP Farm'); $demoFarm = true; } catch (Exception $e) { throw new Exception("Demo farm creation failed: {$e->getMessage()}"); } } } $this->response->success('Environment saved'); $this->response->data(array('enabled' => $enabled, 'demoFarm' => $demoFarm)); } catch (Exception $e) { $this->db->RollbackTrans(); throw new Exception(_("Failed to save AWS settings: {$e->getMessage()}")); } $this->db->CommitTrans(); }
function handleWork($serverId) { try { $dbserver = DBServer::LoadByID($serverId); if ($dbserver->farmId) { if ($dbserver->GetFarmObject()->Status == FARM_STATUS::TERMINATED) { throw new ServerNotFoundException(""); } } } catch (Exception $e) { $this->db->Execute("DELETE FROM messages WHERE server_id=? AND `type`='in'", array($serverId)); return; } $rs = $this->db->Execute("SELECT * FROM messages \n \t\tWHERE server_id = ? AND type = ? AND status = ? \n \t\tORDER BY id ASC", array($serverId, "in", MESSAGE_STATUS::PENDING)); while ($row = $rs->FetchRow()) { try { $message = $this->serializer->unserialize($row["message"]); $event = null; // Update scalarizr package version if ($message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION]) { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_VESION, $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION]); } if ($message->meta[Scalr_Messaging_MsgMeta::SZR_UPD_CLIENT_VERSION]) { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_UPD_CLIENT_VERSION, $message->meta[Scalr_Messaging_MsgMeta::SZR_UPD_CLIENT_VERSION]); } try { if ($message instanceof Scalr_Messaging_Msg_OperationResult) { $this->db->Execute("UPDATE server_operations SET `status` = ? WHERE id = ?", array($message->status, $message->id)); if ($message->status == 'error') { if ($message->name == 'Initialization') { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_IS_INIT_FAILED, 1); } if ($message->error) { $msg = $message->error->message; $trace = $message->error->trace; $handler = $message->error->handler; } $this->db->Execute("INSERT INTO server_operation_progress SET \n\t\t\t\t\t\t\t\t\t`operation_id` = ?,\n\t\t\t\t\t\t\t\t\t`timestamp` = ?,\n\t\t\t\t\t\t\t\t\t`phase` = ?,\n\t\t\t\t\t\t\t\t\t`step` = ?,\n\t\t\t\t\t\t\t\t\t`status` = ?,\n\t\t\t\t\t\t\t\t\t`message`= ?,\n\t\t\t\t\t\t\t\t\t`trace` = ?,\n\t\t\t\t\t\t\t\t\t`handler` = ?,\n\t\t\t\t\t\t\t\t\t`progress` = ?,\n\t\t\t\t\t\t\t\t\t`stepno` = ? \n\t\t\t\t\t\t\t\t\tON DUPLICATE KEY UPDATE status = ?, progress = ?, trace = ?, handler = ?, message = ?\n\t\t\t\t\t\t\t\t", array($message->id, $message->getTimestamp(), $message->phase, $message->step, $message->status, $msg, $trace, $handler, $message->progress, $message->stepno, $message->status, $message->progress, $trace, $handler, $msg)); } } elseif ($message instanceof Scalr_Messaging_Msg_Win_HostDown) { $status = PlatformFactory::NewPlatform($dbserver->platform)->GetServerRealStatus($dbserver); if ($status->isRunning()) { $event = new RebootBeginEvent($dbserver); } else { $event = new HostDownEvent($dbserver); } } elseif ($message instanceof Scalr_Messaging_Msg_Win_PrepareBundleResult) { try { $bundleTask = BundleTask::LoadById($message->bundleTaskId); } catch (Exception $e) { } if ($bundleTask) { if ($message->status == 'ok') { $metaData = array('szr_version' => $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION], 'os' => $message->os, 'software' => $message->software); $bundleTask->setMetaData($metaData); $bundleTask->Save(); PlatformFactory::NewPlatform($bundleTask->platform)->CreateServerSnapshot($bundleTask); } else { $bundleTask->SnapshotCreationFailed("PrepareBundle procedure failed: {$message->lastError}"); } } } elseif ($message instanceof Scalr_Messaging_Msg_DeployResult) { try { $deploymentTask = Scalr_Model::init(Scalr_Model::DM_DEPLOYMENT_TASK)->loadById($message->deployTaskId); } catch (Exception $e) { } if ($deploymentTask) { if ($message->status == 'error') { $deploymentTask->status = Scalr_Dm_DeploymentTask::STATUS_FAILED; $deploymentTask->lastError = $message->lastError; } else { $deploymentTask->status = Scalr_Dm_DeploymentTask::STATUS_DEPLOYED; $deploymentTask->dtDeployed = date("Y-m-d H:i:s"); } $deploymentTask->save(); } } elseif ($message instanceof Scalr_Messaging_Msg_Hello) { $event = $this->onHello($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_MongoDb) { try { $dbFarmRole = $dbserver->GetFarmRoleObject(); } catch (Exception $e) { } if ($dbFarmRole instanceof DBFarmRole) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->handleMessage($message, $dbserver); } } } elseif ($message instanceof Scalr_Messaging_Msg_DbMsr) { try { $dbFarmRole = $dbserver->GetFarmRoleObject(); } catch (Exception $e) { } if ($dbFarmRole instanceof DBFarmRole) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->handleMessage($message, $dbserver); } } } elseif ($message instanceof Scalr_Messaging_Msg_HostInit) { $event = $this->onHostInit($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_HostUp) { $event = $this->onHostUp($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_HostDown) { $isMoving = false; if ($dbserver->platform == SERVER_PLATFORMS::RACKSPACE) { $p = PlatformFactory::NewPlatform($dbserver->platform); $status = $p->GetServerRealStatus($dbserver)->getName(); if (stristr($status, 'MOVE') || stristr($status, 'REBOOT')) { $this->logger->error(new FarmLogMessage($dbserver->farmId, "Rackspace server is in MOVING state. Ignoring HostDown message.")); $isMoving = true; } } if (!$isMoving) { $event = new HostDownEvent($dbserver); } } elseif ($message instanceof Scalr_Messaging_Msg_RebootStart) { $event = new RebootBeginEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_RebootFinish) { $event = new RebootCompleteEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_BeforeHostUp) { $event = new BeforeHostUpEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_BlockDeviceAttached) { if ($dbserver->platform == SERVER_PLATFORMS::EC2) { $ec2Client = Scalr_Service_Cloud_Aws::newEc2($dbserver->GetProperty(EC2_SERVER_PROPERTIES::REGION), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); $instanceId = $dbserver->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID); $volumes = $ec2Client->DescribeVolumes()->volumeSet->item; if (!is_array($volumes)) { $volumes = array($volumes); } foreach ($volumes as $volume) { if ($volume->status == AMAZON_EBS_STATE::IN_USE && $volume->attachmentSet->item->instanceId == $instanceId && $volume->attachmentSet->item->device == $message->deviceName) { $message->volumeId = $volume->volumeId; } } } $event = new EBSVolumeAttachedEvent($dbserver, $message->deviceName, $message->volumeId); } elseif ($message instanceof Scalr_Messaging_Msg_BlockDeviceMounted) { // Single volume $ebsinfo = $this->db->GetRow("SELECT * FROM ec2_ebs WHERE volume_id=?", array($message->volumeId)); if ($ebsinfo) { $this->db->Execute("UPDATE ec2_ebs SET mount_status=?, isfsexist='1' WHERE id=?", array(EC2_EBS_MOUNT_STATUS::MOUNTED, $ebsinfo['id'])); } $event = new EBSVolumeMountedEvent($dbserver, $message->mountpoint, $message->volumeId, $message->deviceName); } elseif ($message instanceof Scalr_Messaging_Msg_RebundleResult) { if ($message->status == Scalr_Messaging_Msg_RebundleResult::STATUS_OK) { $metaData = array('szr_version' => $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION], 'dist' => $message->dist, 'os' => $message->os, 'software' => $message->software); if ($dbserver->platform == SERVER_PLATFORMS::EC2) { if ($message->aws) { if ($message->aws->root - device - type == 'ebs') { $tags[] = ROLE_TAGS::EC2_EBS; } if ($message->aws->virtualization - type == 'hvm') { $tags[] = ROLE_TAGS::EC2_HVM; } } else { $ec2Client = Scalr_Service_Cloud_Aws::newEc2($dbserver->GetProperty(EC2_SERVER_PROPERTIES::REGION), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); try { $DescribeImagesType = new DescribeImagesType(null, array(), null); $DescribeImagesType->imagesSet = new stdClass(); $DescribeImagesType->imagesSet->item = array(); $DescribeImagesType->imagesSet->item[] = array('imageId' => $dbserver->GetProperty(EC2_SERVER_PROPERTIES::AMIID)); $info = $ec2Client->DescribeImages($DescribeImagesType); if ($info->imagesSet->item->rootDeviceType == 'ebs') { $tags[] = ROLE_TAGS::EC2_EBS; } else { try { $bundleTask = BundleTask::LoadById($message->bundleTaskId); if ($bundleTask->bundleType == SERVER_SNAPSHOT_CREATION_TYPE::EC2_EBS) { $tags[] = ROLE_TAGS::EC2_EBS; } } catch (Exception $e) { } } if ($info->imagesSet->item->virtualizationType == 'hvm') { $tags[] = ROLE_TAGS::EC2_HVM; } } catch (Exception $e) { $metaData['tagsError'] = $e->getMessage(); } } } elseif ($dbserver->platform == SERVER_PLATFORMS::NIMBULA) { $metaData['init_root_user'] = $message->sshUser; $metaData['init_root_pass'] = $message->sshPassword; } $metaData['tags'] = $tags; $event = new RebundleCompleteEvent($dbserver, $message->snapshotId, $message->bundleTaskId, $metaData); } else { if ($message->status == Scalr_Messaging_Msg_RebundleResult::STATUS_FAILED) { $event = new RebundleFailedEvent($dbserver, $message->bundleTaskId, $message->lastError); } } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreateDataBundleResult) { if ($message->status == "ok") { $event = new MysqlBackupCompleteEvent($dbserver, MYSQL_BACKUP_TYPE::BUNDLE, array('snapshotConfig' => $message->snapshotConfig, 'logFile' => $message->logFile, 'logPos' => $message->logPos, 'dataBundleSize' => $message->dataBundleSize, 'snapshotId' => $message->snapshotId)); } else { $event = new MysqlBackupFailEvent($dbserver, MYSQL_BACKUP_TYPE::BUNDLE); $event->lastError = $message->lastError; } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreateBackupResult) { if ($message->status == "ok") { $event = new MysqlBackupCompleteEvent($dbserver, MYSQL_BACKUP_TYPE::DUMP); } else { $event = new MysqlBackupFailEvent($dbserver, MYSQL_BACKUP_TYPE::DUMP); $event->lastError = $message->lastError; } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_PromoteToMasterResult) { $event = $this->onMysql_PromoteToMasterResult($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreatePmaUserResult) { $farmRole = DBFarmRole::LoadByID($message->farmRoleId); if ($message->status == "ok") { $farmRole->SetSetting(DbFarmRole::SETTING_MYSQL_PMA_USER, $message->pmaUser); $farmRole->SetSetting(DbFarmRole::SETTING_MYSQL_PMA_PASS, $message->pmaPassword); } else { $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_REQUEST_TIME, ""); $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_REQUEST_ERROR, $message->lastError); } } elseif ($message instanceof Scalr_Messaging_Msg_RabbitMq_SetupControlPanelResult) { $farmRole = $dbserver->GetFarmRoleObject(); if ($message->status == "ok") { $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_SERVER_ID, $dbserver->serverId); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_URL, $message->cpanelUrl); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME, ""); } else { $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_SERVER_ID, ""); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME, ""); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_ERROR_MSG, $message->lastError); } } elseif ($message instanceof Scalr_Messaging_Msg_AmiScriptsMigrationResult) { try { //Open security group: if ($dbserver->platform == SERVER_PLATFORMS::EC2) { $info = PlatformFactory::NewPlatform($dbserver->platform)->GetServerExtendedInformation($dbserver); $sg = explode(", ", $info['Security groups']); foreach ($sg as $sgroup) { if ($sgroup != 'default') { $ipPermissionSet = new IpPermissionSetType(); $group_rules = array(array('rule' => 'tcp:8013:8013:0.0.0.0/0'), array('rule' => 'udp:8014:8014:0.0.0.0/0')); foreach ($group_rules as $rule) { $group_rule = explode(":", $rule["rule"]); $ipPermissionSet->AddItem($group_rule[0], $group_rule[1], $group_rule[2], null, array($group_rule[3])); } $ec2Client = Scalr_Service_Cloud_Aws::newEc2($dbserver->GetProperty(EC2_SERVER_PROPERTIES::REGION), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); // Create security group $ec2Client->AuthorizeSecurityGroupIngress($dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::ACCOUNT_ID), $sgroup, $ipPermissionSet); break; } } } } catch (Exception $e) { $this->logger->fatal($e->getMessage()); } $dbserver->SetProperty(SERVER_PROPERTIES::SZR_SNMP_PORT, 8014); $dbserver->SetProperty(SERVER_PROPERTIES::SZR_VESION, "0.7.217"); if ($message->mysql) { $event = $this->onHostUp($message, $dbserver, true); } } $handle_status = MESSAGE_STATUS::HANDLED; } catch (Exception $e) { $handle_status = MESSAGE_STATUS::FAILED; $this->logger->error(sprintf("Cannot handle message '%s' (message_id: %s) " . "from server '%s' (server_id: %s). %s", $message->getName(), $message->messageId, $dbserver->remoteIp ? $dbserver->remoteIp : '*no-ip*', $dbserver->serverId, $e->getMessage() . "({$e->getFile()}:{$e->getLine()})")); } $this->db->Execute("UPDATE messages SET status = ? WHERE messageid = ?", array($handle_status, $message->messageId)); if ($event) { Scalr::FireEvent($dbserver->farmId, $event); } } catch (Exception $e) { $this->logger->error($e->getMessage(), $e); } } }
function handleWork($farmId) { $DBFarm = DBFarm::LoadByID($farmId); $GLOBALS["SUB_TRANSACTIONID"] = abs(crc32(posix_getpid() . $farmId)); $GLOBALS["LOGGER_FARMID"] = $farmId; if ($DBFarm->Status != FARM_STATUS::RUNNING) { $this->logger->warn("[FarmID: {$DBFarm->ID}] Farm terminated. There is no need to scale it."); return; } foreach ($DBFarm->GetFarmRoles() as $DBFarmRole) { for ($i = 0; $i < 10; $i++) { if ($DBFarmRole->NewRoleID != '') { $this->logger->warn("[FarmID: {$DBFarm->ID}] Role '{$DBFarmRole->GetRoleObject()->name}' being synchronized. This role will not be scalled."); continue 2; } if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_ENABLED) == '0' && !$DBFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::MONGODB)) { $this->logger->info("[FarmID: {$DBFarm->ID}] Scaling disabled for role '{$DBFarmRole->GetRoleObject()->name}'. Skipping..."); continue 2; } // Get polling interval in seconds $polling_interval = $DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_POLLING_INTERVAL) * 60; $dt_last_polling = $DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_LAST_POLLING_TIME); if ($dt_last_polling && $dt_last_polling + $polling_interval > time() && $i == 0) { $this->logger->info("Polling interval: every {$polling_interval} seconds"); //continue; } // Set Last polling time $DBFarmRole->SetSetting(DBFarmRole::SETTING_SCALING_LAST_POLLING_TIME, time()); // Get current count of running and pending instances. $this->logger->info(sprintf("Processing role '%s'", $DBFarmRole->GetRoleObject()->name)); $scalingManager = new Scalr_Scaling_Manager($DBFarmRole); $scalingDecision = $scalingManager->makeScalingDecition(); if ($scalingDecision == Scalr_Scaling_Decision::STOP_SCALING) { return; } if ($scalingDecision == Scalr_Scaling_Decision::NOOP) { continue 2; } elseif ($scalingDecision == Scalr_Scaling_Decision::DOWNSCALE) { /* Timeout instance's count decrease. Decreases instance�s count after scaling resolution the spare instances are running�g for selected timeout interval from scaling EditOptions */ // We have to check timeout limits before new scaling (downscaling) process will be initiated if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_DOWNSCALE_TIMEOUT_ENABLED)) { // if the farm timeout is exceeded // checking timeout interval. $last_down_scale_data_time = $DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_DOWNSCALE_DATETIME); $timeout_interval = $DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_DOWNSCALE_TIMEOUT); // check the time interval to continue scaling or cancel it... if (time() - $last_down_scale_data_time < $timeout_interval * 60) { // if the launch time is too small to terminate smth in this role -> go to the next role in foreach() Logger::getLogger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBFarm->ID, sprintf("Waiting for downscaling timeout on farm %s, role %s", $DBFarm->Name, $DBFarmRole->GetRoleObject()->name))); continue 2; } } // end Timeout instance's count decrease $sort = $DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_KEEP_OLDEST) == 1 ? 'DESC' : 'ASC'; $servers = $this->db->GetAll("SELECT server_id FROM servers WHERE status = ? AND farm_roleid=? ORDER BY dtadded {$sort}", array(SERVER_STATUS::RUNNING, $DBFarmRole->ID)); $got_valid_instance = false; // Select instance that will be terminated // // * Instances ordered by uptime (oldest wil be choosen) // * Instance cannot be mysql master // * Choose the one that was rebundled recently while (!$got_valid_instance && count($servers) > 0) { $item = array_shift($servers); $DBServer = DBServer::LoadByID($item['server_id']); if ($DBServer->GetFarmRoleObject()->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) { $serversCount = count($DBServer->GetFarmRoleObject()->GetServersByFilter(array(), array('status' => SERVER_STATUS::TERMINATED))); if ($DBServer->index == 1 && $serversCount > 1) { continue; } } // Exclude db master if ($DBServer->GetProperty(SERVER_PROPERTIES::DB_MYSQL_MASTER) != 1 && $DBServer->GetProperty(Scalr_Db_Msr::REPLICATION_MASTER) != 1) { /* * We do not want to delete the most recently synced instance. Because of LA fluctuation. * I.e. LA may skyrocket during sync and drop dramatically after sync. */ if ($DBServer->dateLastSync != 0) { $chk_sync_time = $this->db->GetOne("SELECT server_id FROM servers \n\t \t\tWHERE dtlastsync > {$DBServer->dateLastSync} \n\t\t \tAND farm_roleid='{$DBServer->farmRoleId}' AND status != '" . SERVER_STATUS::TERMINATED . "'"); if ($chk_sync_time) { $got_valid_instance = true; } } else { $got_valid_instance = true; } } } if ($DBServer && $got_valid_instance) { $this->logger->info(sprintf("Server '%s' selected for termination...", $DBServer->serverId)); $allow_terminate = false; if ($DBServer->platform == SERVER_PLATFORMS::EC2) { $AmazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($DBServer->GetProperty(EC2_SERVER_PROPERTIES::REGION), $DBServer->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $DBServer->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); // Shutdown an instance just before a full hour running $response = $AmazonEC2Client->DescribeInstances($DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID)); if ($response && $response->reservationSet->item) { $launch_time = strtotime($response->reservationSet->item->instancesSet->item->launchTime); $time = 3600 - (time() - $launch_time) % 3600; // Terminate instance in < 10 minutes for full hour. if ($time <= 600) { $allow_terminate = true; } else { $timeout = round(($time - 600) / 60, 1); Logger::getLogger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBFarm->ID, sprintf("Farm %s, role %s scaling down. Server '%s' will be terminated in %s minutes. Launch time: %s", $DBFarm->Name, $DBServer->GetFarmRoleObject()->GetRoleObject()->name, $DBServer->serverId, $timeout, $response->reservationSet->item->instancesSet->item->launchTime))); } } // } else { $allow_terminate = true; } if ($allow_terminate) { //Check safe shutdown if ($DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_SCALING_SAFE_SHUTDOWN) == 1) { $snmpClient = new Scalr_Net_Snmp_Client(); $port = $DBServer->GetProperty(SERVER_PROPERTIES::SZR_SNMP_PORT); $snmpClient->connect($DBServer->remoteIp, $port ? $port : 161, $DBFarm->Hash, null, null, false); $res = $snmpClient->get('1.3.6.1.4.1.36632.6.1'); if ($res != '1') { Logger::getLogger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBFarm->ID, sprintf("Safe shutdown enabled. Server '%s'. Script return '%s', server won't be terminated while return value not '1'", $DBServer->serverId, $res))); } } try { Scalr::FireEvent($DBFarm->ID, new BeforeHostTerminateEvent($DBServer, false)); $DBFarmRole->SetSetting(DBFarmRole::SETTING_SCALING_DOWNSCALE_DATETIME, time()); Logger::getLogger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBFarm->ID, sprintf("Farm %s, role %s scaling down. Server '%s' marked as 'Pending terminate' and will be fully terminated in 3 minutes.", $DBFarm->Name, $DBServer->GetFarmRoleObject()->GetRoleObject()->name, $DBServer->serverId))); } catch (Exception $e) { $this->logger->fatal(sprintf("Cannot terminate %s: %s", $DBFarm->ID, $DBServer->serverId, $e->getMessage())); } } } else { $this->logger->warn(sprintf("[FarmID: {$DBFarm->ID}] Scalr unable to determine what instance it should terminate (FarmRoleID: {$DBFarmRole->ID}). Skipping...")); } break; } elseif ($scalingDecision == Scalr_Scaling_Decision::UPSCALE) { /* Timeout instance's count increase. Increases instance's count after scaling resolution �need more instances� for selected timeout interval from scaling EditOptions */ if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_UPSCALE_TIMEOUT_ENABLED)) { // if the farm timeout is exceeded // checking timeout interval. $last_up_scale_data_time = $DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_UPSCALE_DATETIME); $timeout_interval = $DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_UPSCALE_TIMEOUT); // check the time interval to continue scaling or cancel it... if (time() - $last_up_scale_data_time < $timeout_interval * 60) { // if the launch time is too small to terminate smth in this role -> go to the next role in foreach() Logger::getLogger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBFarm->ID, sprintf("Waiting for upscaling timeout on farm %s, role %s", $DBFarm->Name, $DBFarmRole->GetRoleObject()->name))); continue 2; } } // end Timeout instance's count increase if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_SCALING_ONE_BY_ONE) == 1) { $pendingInstances = $DBFarmRole->GetPendingInstancesCount(); if ($pendingInstances > 0) { Logger::getLogger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBFarm->ID, sprintf("There are %s pending intances of %s role on % farm. Waiting...", $pendingInstances, $DBFarmRole->GetRoleObject()->name, $DBFarm->Name))); continue 2; } } $fstatus = $this->db->GetOne("SELECT status FROM farms WHERE id=?", array($DBFarm->ID)); if ($fstatus != FARM_STATUS::RUNNING) { $this->logger->warn("[FarmID: {$DBFarm->ID}] Farm terminated. There is no need to scale it."); return; } $ServerCreateInfo = new ServerCreateInfo($DBFarmRole->Platform, $DBFarmRole); try { $DBServer = Scalr::LaunchServer($ServerCreateInfo); $DBFarmRole->SetSetting(DBFarmRole::SETTING_SCALING_UPSCALE_DATETIME, time()); Logger::getLogger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBFarm->ID, sprintf("Farm %s, role %s scaling up. Starting new instance. ServerID = %s.", $DBFarm->Name, $DBServer->GetFarmRoleObject()->GetRoleObject()->name, $DBServer->serverId))); } catch (Exception $e) { Logger::getLogger(LOG_CATEGORY::SCALING)->error($e->getMessage()); } } } } }
/** * Return new instance of AmazonEC2 object * * @return AmazonEC2 */ private function GetAmazonEC2ClientObject(Scalr_Environment $environment, $region) { // Return new instance of AmazonEC2 object $AmazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($region, $environment->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $environment->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); return $AmazonEC2Client; }
public static function farmSave(DBFarm $DBFarm, array $roles) { $buckets = array(); foreach ($roles as $DBFarmRole) { if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_AWS_S3_BUCKET)) { $buckets[$DBFarmRole->CloudLocation] = $DBFarmRole->GetSetting(DBFarmRole::SETTING_AWS_S3_BUCKET); } } foreach ($roles as $DBFarmRole) { if ($DBFarmRole->Platform != SERVER_PLATFORMS::EC2) { continue; } $location = $DBFarmRole->CloudLocation; $sshKey = Scalr_Model::init(Scalr_Model::SSH_KEY); if (!$sshKey->loadGlobalByFarmId($DBFarm->ID, $location)) { $key_name = "FARM-{$DBFarm->ID}"; $AmazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($location, $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); $result = $AmazonEC2Client->CreateKeyPair($key_name); if ($result->keyMaterial) { $sshKey->farmId = $DBFarm->ID; $sshKey->clientId = $DBFarm->ClientID; $sshKey->envId = $DBFarm->EnvID; $sshKey->type = Scalr_SshKey::TYPE_GLOBAL; $sshKey->cloudLocation = $location; $sshKey->cloudKeyName = $key_name; $sshKey->platform = SERVER_PLATFORMS::EC2; $sshKey->setPrivate($result->keyMaterial); $sshKey->save(); } } try { if (!$DBFarmRole->GetSetting(DBFarmRole::SETTING_AWS_S3_BUCKET)) { if (!$buckets[$location]) { $aws_account_id = $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::ACCOUNT_ID); $bucket_name = "farm-{$DBFarm->Hash}-{$aws_account_id}-{$location}"; // // Create S3 Bucket (For MySQL, BackUs, etc.) // $AmazonS3 = new AmazonS3($DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::ACCESS_KEY), $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::SECRET_KEY)); $buckets = $AmazonS3->ListBuckets(); $create_bucket = true; foreach ($buckets as $bucket) { if ($bucket->Name == $bucket_name) { $create_bucket = false; $buckets[$location] = $bucket_name; break; } } if ($create_bucket) { if ($AmazonS3->CreateBucket($bucket_name, $location)) { $buckets[$location] = $bucket_name; } } } $DBFarmRole->SetSetting(DBFarmRole::SETTING_AWS_S3_BUCKET, $buckets[$location]); } } catch (Exception $e) { throw new Exception("Amazon S3: {$e->getMessage()}"); } } }