protected function ListEBSMountpoints()
 {
     $ResponseDOMDocument = $this->CreateResponse();
     $MountpointsDOMNode = $ResponseDOMDocument->createElement("mountpoints");
     //
     // List EBS Volumes
     //
     if ($this->DBServer->IsSupported("0.7.36")) {
         $volumes = $this->DB->GetAll("SELECT id FROM ec2_ebs WHERE farm_roleid=? AND server_index=?", array($this->DBServer->farmRoleId, $this->DBServer->index));
     } else {
         $volumes = $this->DB->GetAll("SELECT id FROM ec2_ebs WHERE server_id=? AND attachment_status = ? AND mount_status IN (?,?)", array($this->DBServer->serverId, EC2_EBS_ATTACH_STATUS::ATTACHED, EC2_EBS_MOUNT_STATUS::MOUNTED, EC2_EBS_MOUNT_STATUS::MOUNTING));
     }
     $DBFarmRole = $this->DBServer->GetFarmRoleObject();
     if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_AWS_USE_EBS) == 0) {
         $volumes = array();
     }
     foreach ($volumes as $volume) {
         $DBEBSVolume = DBEBSVolume::loadById($volume['id']);
         $mountpoint = $DBEBSVolume->mountPoint ? $DBEBSVolume->mountPoint : "";
         if (!$DBEBSVolume->isManual && $mountpoint) {
             $createfs = $DBEBSVolume->isFsExists ? 0 : 1;
         } else {
             $createfs = 0;
         }
         if ($mountpoint || $this->DBServer->IsSupported("0.7.36")) {
             $mountpoints[] = array('name' => $DBEBSVolume->attachmentStatus == EC2_EBS_ATTACH_STATUS::CREATING ? "vol-creating" : $DBEBSVolume->volumeId, 'dir' => $mountpoint, 'createfs' => $createfs, 'volumes' => array($DBEBSVolume), 'isarray' => 0);
         }
     }
     //
     // Create response
     //
     $MountpointDOMNode = $ResponseDOMDocument->createElement("mountpoint");
     if (!empty($mountpoints)) {
         foreach ($mountpoints as $mountpoint) {
             $MountpointDOMNode->setAttribute("name", $mountpoint['name']);
             $MountpointDOMNode->setAttribute("dir", $mountpoint['dir']);
             $MountpointDOMNode->setAttribute("createfs", $mountpoint['createfs']);
             $MountpointDOMNode->setAttribute("isarray", $mountpoint['isarray']);
             $VolumesDOMNode = $ResponseDOMDocument->createElement("volumes");
             foreach ($mountpoint['volumes'] as $DBEBSVolume) {
                 $VolumeDOMNode = $ResponseDOMDocument->createElement("volume");
                 $VolumeDOMNode->setAttribute("device", $DBEBSVolume->deviceName);
                 $VolumeDOMNode->setAttribute("volume-id", $DBEBSVolume->volumeId);
                 $VolumesDOMNode->appendChild($VolumeDOMNode);
             }
             $MountpointDOMNode->appendChild($VolumesDOMNode);
             $MountpointsDOMNode->appendChild($MountpointDOMNode);
         }
     }
     $ResponseDOMDocument->documentElement->appendChild($MountpointsDOMNode);
     return $ResponseDOMDocument;
 }
Esempio n. 2
0
 /**
  * {@inheritdoc}
  * @see \Scalr\System\Pcntl\ProcessInterface::StartThread()
  */
 public function StartThread($volume)
 {
     $DBEBSVolume = DBEBSVolume::loadById($volume['id']);
     $aws = $DBEBSVolume->getEnvironmentObject()->aws($DBEBSVolume);
     if ($DBEBSVolume->volumeId) {
         try {
             $volumeinfo = $aws->ec2->volume->describe($DBEBSVolume->volumeId)->get(0);
         } 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}");
             }
         }
     }
     $attach_volume = null;
     switch ($DBEBSVolume->attachmentStatus) {
         case EC2_EBS_ATTACH_STATUS::DELETING:
             if ($DBEBSVolume->volumeId) {
                 try {
                     $aws->ec2->volume->delete($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->get(0)->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 {
                             $aws->ec2->volume->detach($DBEBSVolume->volumeId, $volumeInstanceId, $DBEBSVolume->deviceName, true);
                         } 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();
                     }
                 }
                 try {
                     $req = new CreateVolumeRequestData($DBEBSVolume->ec2AvailZone, $DBEBSVolume->size);
                     $req->volumeType = $DBEBSVolume->type;
                     if (!empty($DBEBSVolume->snapId)) {
                         $req->snapshotId = $DBEBSVolume->snapId;
                     }
                     if ($req->volumeType == 'io1') {
                         $req->iops = $DBEBSVolume->iops;
                     }
                     $result = $aws->ec2->volume->create($req);
                     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")) {
                         $matches = [];
                         @preg_match_all("/(([0-9]+)GiB)/sim", $e->getMessage(), $matches);
                         if (!empty($matches[2][1]) && $matches[2][1] > 1) {
                             $DBEBSVolume->size = $matches[2][1];
                             $DBEBSVolume->save();
                         }
                     }
                     if ($DBEBSVolume->farmId) {
                         $this->logger->error(new FarmLogMessage(!empty($DBEBSVolume->farmId) ? $DBEBSVolume->farmId : null, "Cannot create volume: {$e->getMessage()}", !empty($DBEBSVolume->serverId) ? $DBEBSVolume->serverId : null, !empty($DBEBSVolume->envId) ? $DBEBSVolume->envId : null, !empty($DBEBSVolume->farmRoleId) ? $DBEBSVolume->farmRoleId : null));
                     } else {
                         $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();
                 return;
             }
         } catch (\Scalr\Exception\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->GetOsType() == 'windows') {
                 return;
             }
             try {
                 $device = $DBServer->GetFreeDeviceName();
                 $result = $aws->ec2->volume->attach($DBEBSVolume->volumeId, $DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID), $device);
             } 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()}");
                 }
                 return false;
             }
             if ($result && $result->status == AMAZON_EBS_STATE::IN_USE || $result->status == AMAZON_EBS_STATE::ATTACHING) {
                 $DBEBSVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::ATTACHING;
                 $DBEBSVolume->deviceName = $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 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}");
             }
         }
     }
 }