cloud-8.x-2.0-beta1/modules/cloud_service_providers/aws_cloud/src/Service/Ec2/Ec2BatchOperations.php

modules/cloud_service_providers/aws_cloud/src/Service/Ec2/Ec2BatchOperations.php
<?php

namespace Drupal\aws_cloud\Service\Ec2;

use Drupal\aws_cloud\Entity\Ec2\Volume;
use Drupal\aws_cloud\Entity\Ec2\Snapshot;
use Drupal\aws_cloud\Entity\Ec2\KeyPair;
use Drupal\aws_cloud\Entity\Ec2\ElasticIp;
use Drupal\aws_cloud\Entity\Ec2\NetworkInterface;
use Drupal\aws_cloud\Entity\Ec2\Image;
use Drupal\aws_cloud\Entity\Ec2\Instance;
use Drupal\aws_cloud\Entity\Ec2\SecurityGroup;
use Drupal\aws_cloud\Entity\Vpc\Vpc;
use Drupal\aws_cloud\Entity\Vpc\Subnet;
use Drupal\cloud\Entity\CloudServerTemplate;

/**
 * Entity update methods for Batch API processing.
 */
class Ec2BatchOperations {

  /**
   * The finish callback function.
   *
   * Deletes stale entities from the database.
   *
   * @param string $entity_type
   *   The entity type.
   * @param array $stale
   *   The stale entities to delete.
   * @param bool $clear
   *   TRUE to clear entities, FALSE keep them.
   */
  public static function finished($entity_type, array $stale, $clear = TRUE) {
    $entity_type_manager = \Drupal::entityTypeManager();
    if (count($stale) && $clear == TRUE) {
      $entity_type_manager->getStorage($entity_type)->delete($stale);
    }
  }

  /**
   * Update or create an instance entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $instance
   *   The instance array.
   */
  public static function updateInstance($cloud_context, array $instance) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);
    $timestamp = time();

    $config_factory = \Drupal::configFactory();

    // Get instance IAM roles associated to instances.
    $instance_iam_roles = [];
    $associations_result = $ec2Service->describeIamInstanceProfileAssociations();
    foreach ($associations_result['IamInstanceProfileAssociations'] ?: [] as $association) {
      $instance_iam_roles[$association['InstanceId']]
        = $association['IamInstanceProfile']['Arn'];
    }

    $instanceName = '';
    $uid = 0;
    $termination_timestamp = NULL;
    $schedule = '';
    $tags = [];
    if (!isset($instance['Tags'])) {
      $instance['Tags'] = [];
    }
    foreach ($instance['Tags'] ?: [] as $tag) {
      if ($tag['Key'] == 'Name') {
        $instanceName = $tag['Value'];
      }
      if ($tag['Key'] == Instance::TAG_LAUNCHED_BY_UID) {
        $uid = $tag['Value'];
      }
      if ($tag['Key'] == Instance::TAG_TERMINATION_TIMESTAMP) {
        if ($tag['Value'] != '') {
          $termination_timestamp = (int) $tag['Value'];
        }
      }
      if ($tag['Key'] == $config_factory->get('aws_cloud.settings')->get('aws_cloud_scheduler_tag')) {
        $schedule = $tag['Value'];
      }

      $tags[] = ['tag_key' => $tag['Key'], 'tag_value' => $tag['Value']];
    }

    usort($tags, function ($a, $b) {
      if ($a['tag_key'] == 'Name') {
        return -1;
      }

      if ($b['tag_key'] == 'Name') {
        return 1;
      }

      return strcmp($a['tag_key'], $b['tag_key']);
    });

    // Default to instance_id.
    if (empty($instanceName)) {
      $instanceName = $instance['InstanceId'];
    }

    $security_groups = [];
    foreach ($instance['SecurityGroups'] ?: [] as $security_group) {
      $security_groups[] = $security_group['GroupName'];
    }

    // Termination protection.
    $attribute_result = $ec2Service->describeInstanceAttribute([
      'InstanceId' => $instance['InstanceId'],
      'Attribute' => 'disableApiTermination',
    ]);
    $termination_protection = $attribute_result['DisableApiTermination']['Value'];

    // Get user data.
    $attribute_result = $ec2Service->describeInstanceAttribute([
      'InstanceId' => $instance['InstanceId'],
      'Attribute' => 'userData',
    ]);
    $user_data = '';
    if (!empty($attribute_result['UserData']['Value'])) {
      $user_data = base64_decode($attribute_result['UserData']['Value']);
    }

    // Instance IAM roles.
    $iam_role = NULL;
    if (isset($instance_iam_roles[$instance['InstanceId']])) {
      $iam_role = $instance_iam_roles[$instance['InstanceId']];
    }

    // Use NetworkInterface to look up private IPs.  In EC2-VPC,
    // an instance can have more than one private IP.
    $network_interfaces = [];
    $private_ips = FALSE;

    if (isset($instance['NetworkInterfaces'])) {
      $private_ips = $ec2Service->getPrivateIps($instance['NetworkInterfaces']);
      foreach ($instance['NetworkInterfaces'] ?: [] as $interface) {
        $network_interfaces[] = $interface['NetworkInterfaceId'];
      }
    }

    // Get instance types.
    $instance_types = aws_cloud_get_instance_types($cloud_context);
    $entity_id = $ec2Service->getEntityId('aws_cloud_instance', 'instance_id', $instance['InstanceId']);
    $cost = $ec2Service->calculateInstanceCost($instance, $instance_types);
    // Skip if $entity already exists, by updating 'refreshed' time.
    if (!empty($entity_id)) {
      /* @var \Drupal\aws_cloud\Entity\Ec2\Instance $entity */
      $entity = Instance::load($entity_id);
      $entity->setName($instanceName);
      $entity->setInstanceState($instance['State']['Name']);

      // Set attributes that are available when system starts up.
      $public_ip = NULL;

      if ($private_ips != FALSE) {
        $entity->setPrivateIps($private_ips);
      }
      if (isset($instance['PublicIpAddress'])) {
        $public_ip = $instance['PublicIpAddress'];
      }
      if (isset($instance['PublicDnsName'])) {
        $entity->setPublicDns($instance['PublicDnsName']);
      }
      if (isset($instance['PrivateDnsName'])) {
        $entity->setPrivateDns($instance['PrivateDnsName']);
      }

      $entity->setPublicIp($public_ip);
      $entity->setSecurityGroups(implode(', ', $security_groups));
      $entity->setInstanceType($instance['InstanceType']);
      $entity->setRefreshed($timestamp);
      $entity->setLaunchTime(strtotime($instance['LaunchTime']->__toString()));
      $entity->setTerminationTimestamp($termination_timestamp);
      $entity->setTerminationProtection($termination_protection);
      $entity->setUserData($user_data);
      $entity->setSchedule($schedule);
      $entity->setTags($tags);
      $entity->setIamRole($iam_role);
      $entity->setNetworkInterfaces($network_interfaces);
      $entity->setCost($cost);

      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
      $entity->save();
    }
    else {
      $entity = Instance::create([
        'cloud_context' => $cloud_context,
        'name' => !empty($instanceName) ? $instanceName : $instance['InstanceId'],
        'account_id' => $instance['reservation_ownerid'],
        'security_groups' => implode(', ', $security_groups),
        'instance_id' => $instance['InstanceId'],
        'instance_type' => $instance['InstanceType'],
        'availability_zone' => $instance['Placement']['AvailabilityZone'],
        'tenancy' => $instance['Placement']['Tenancy'],
        'instance_state' => $instance['State']['Name'],
        'public_dns' => $instance['PublicDnsName'],
        'public_ip' => isset($instance['PublicIpAddress']) ? $instance['PublicIpAddress'] : NULL,
        'private_dns' => $instance['PrivateDnsName'],
        'key_pair_name' => $instance['KeyName'],
        'is_monitoring' => $instance['Monitoring']['State'],
        'vpc_id' => $instance['VpcId'],
        'subnet_id' => $instance['SubnetId'],
        'source_dest_check' => $instance['SourceDestCheck'],
        'ebs_optimized' => $instance['EbsOptimized'],
        'root_device_type' => $instance['RootDeviceType'],
        'root_device' => $instance['RootDeviceName'],
        'image_id' => $instance['ImageId'],
        'placement_group' => $instance['Placement']['GroupName'],
        'virtualization' => $instance['VirtualizationType'],
        'reservation' => $instance['reservation_id'],
        'ami_launch_index' => $instance['AmiLaunchIndex'],
        'host_id' => isset($instance['Placement']['HostId']) ? $instance['Placement']['HostId'] : NULL,
        'affinity' => isset($instance['Placement']['Affinity']) ? $instance['Placement']['Affinity'] : NULL,
        'state_transition_reason' => $instance['StateTransitionReason'],
        'instance_lock' => FALSE,
        'launch_time' => strtotime($instance['LaunchTime']->__toString()),
        'created' => strtotime($instance['LaunchTime']->__toString()),
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
        'termination_timestamp' => $termination_timestamp,
        'termination_protection' => $termination_protection,
        'user_data' => $user_data,
        'schedule' => $schedule,
        'tags' => $tags,
        'iam_role' => $iam_role,
        'cost' => $cost,
      ]);

      if ($private_ips != FALSE) {
        $entity->setPrivateIps($private_ips);
      }
      $entity->setNetworkInterfaces($network_interfaces);
      $entity->save();
    }
  }

  /**
   * Update or create a image entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $image
   *   The image array.
   */
  public static function updateImage($cloud_context, array $image) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);
    $timestamp = time();

    $block_devices = [];
    foreach ($image['BlockDeviceMappings'] ?: [] as $block_device) {
      $block_devices[] = $block_device['DeviceName'];
    }

    $name = $ec2Service->getTagName($image, $image['Name']);
    $uid = $ec2Service->getUidTagValue($image, Image::TAG_CREATED_BY_UID);
    $entity_id = $ec2Service->getEntityId('aws_cloud_image', 'image_id', $image['ImageId']);

    // Skip if $entity already exists, by updating 'refreshed' time.
    if (!empty($entity_id)) {
      $entity = Image::load($entity_id);
      $entity->setName($name);
      $entity->setRefreshed($timestamp);
      $entity->setVisibility($image['Public']);
      $entity->setStatus($image['State']);

      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
      $entity->save();
    }
    else {
      $entity = Image::create([
        'cloud_context' => $cloud_context,
        'image_id' => $image['ImageId'],
        'account_id' => $image['OwnerId'],
        'architecture' => $image['Architecture'],
        'virtualization_type' => $image['VirtualizationType'],
        'root_device_type' => $image['RootDeviceType'],
        'root_device_name' => $image['RootDeviceName'],
        'ami_name' => $image['Name'],
        'name' => $image['Name'],
        'kernel_id' => isset($image['KernelId']) ? $image['KernelId'] : '',
        'ramdisk_id' => isset($image['RamdiskId']) ? $image['RamdiskId'] : '',
        'image_type' => $image['ImageType'],
        'product_code' => isset($image['ProductCodes']) ? implode(',', array_column($image['ProductCodes'], 'ProductCode')) : '',
        'source' => $image['ImageLocation'],
        'state_reason' => isset($image['StateReason']) ? $image['StateReason']['Message'] : '',
        'platform' => isset($image['Platform']) ? $image['Platform'] : '',
        'description' => isset($image['Description']) ? $image['Description'] : '',
        'visibility' => $image['Public'],
        'block_devices' => implode(', ', $block_devices),
        'status' => $image['State'],
        'created' => strtotime($image['CreationDate']),
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
      $entity->save();
    }
  }

  /**
   * Update or create a security group entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $security_group
   *   The security_group array.
   */
  public static function updateSecurityGroup($cloud_context, array $security_group) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $ec2Service->getTagName($security_group, $security_group['GroupName']);
    $uid = $ec2Service->getUidTagValue($security_group, SecurityGroup::TAG_CREATED_BY_UID);
    $entity_id = $ec2Service->getEntityId('aws_cloud_security_group', 'group_id', $security_group['GroupId']);

    // Skip if $entity already exists, by updating 'refreshed' time.
    if (!empty($entity_id)) {
      /* @var \Drupal\aws_cloud\Entity\Ec2\SecurityGroup $entity */
      $entity = SecurityGroup::load($entity_id);
      $entity->setName($name);
      $entity->setRefreshed($timestamp);
      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
    }
    else {
      // Create a brand new SecurityGroup entity.
      $entity = SecurityGroup::create([
        'cloud_context' => $cloud_context,
        'name' => !empty($security_group['GroupName']) ? $security_group['GroupName'] : $security_group['GroupId'],
        'group_id' => $security_group['GroupId'],
        'group_name' => $security_group['GroupName'],
        'description' => $security_group['Description'],
        'vpc_id' => $security_group['VpcId'],
        'account_id' => $security_group['OwnerId'],
        'created' => $timestamp,
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
    }

    if (isset($security_group['VpcId']) && !empty($security_group['VpcId'])) {
      // Check if VPC is default.  This involves another API call.
      $vpcs = $ec2Service->describeVpcs([
        'VpcIds' => [$security_group['VpcId']],
      ]);
      if ($vpcs['Vpcs']) {
        $default = $vpcs['Vpcs'][0]['IsDefault'];
        $entity->setDefaultVpc($default);
      }
    }

    // Setup the Inbound permissions.
    if (isset($security_group['IpPermissions'])) {
      $ec2Service->setupIpPermissions($entity, 'ip_permission', $security_group['IpPermissions']);
    }

    // Setup outbound permissions.
    if (isset($security_group['VpcId']) && isset($security_group['IpPermissionsEgress'])) {
      $ec2Service->setupIpPermissions($entity, 'outbound_permission', $security_group['IpPermissionsEgress']);
    }
    $entity->save();
  }

  /**
   * Update or create a network interface entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $network_interface
   *   The network interface array.
   */
  public static function updateNetworkInterface($cloud_context, array $network_interface) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);
    $timestamp = time();

    // Set up the primary and secondary private IP addresses.
    // Setup the allocation_ids.  The allocation_ids are used during Elastic
    // IP assignment.
    $primary_private_ip = NULL;
    $secondary_private_ip = NULL;
    $primary_association_id = NULL;
    $secondary_association_id = NULL;
    $public_ips = NULL;

    foreach ($network_interface['PrivateIpAddresses'] ?: [] as $private_ip_address) {
      if ($private_ip_address['Primary'] == TRUE) {
        $primary_private_ip = $private_ip_address['PrivateIpAddress'];
        if (isset($private_ip_address['Association'])) {
          if (!empty($private_ip_address['Association']['AssociationId'])) {
            $primary_association_id = $private_ip_address['Association']['AssociationId'];
          }
          if (!empty($private_ip_address['Association']['PublicIp'])) {
            $public_ips[] = $private_ip_address['Association']['PublicIp'];
          }
        }
      }
      else {
        $secondary_private_ip = $private_ip_address['PrivateIpAddress'];
        if (isset($private_ip_address['Association'])) {
          if (!empty($private_ip_address['Association']['AssociationId'])) {
            $secondary_association_id = $private_ip_address['Association']['AssociationId'];
          }
          if (!empty($private_ip_address['Association']['PublicIp'])) {
            $public_ips[] = $private_ip_address['Association']['PublicIp'];
          }
        }
      }
    }

    $security_groups = [];
    foreach ($network_interface['Groups'] ?: [] as $security_group) {
      $security_groups[] = $security_group['GroupName'];
    }

    // The tag key of the network interface is 'TagSet'.
    // So changing the key to align to other entities.
    // If this key changes to 'Tags' on AWS API, this block needs to be deleted.
    if (isset($network_interface['TagSet'])) {
      $network_interface['Tags'] = $network_interface['TagSet'];
    }

    $name = $ec2Service->getTagName($network_interface, $network_interface['NetworkInterfaceId']);
    $uid = $ec2Service->getUidTagValue($network_interface, NetworkInterface::TAG_CREATED_BY_UID);
    $entity_id = $ec2Service->getEntityId('aws_cloud_network_interface', 'network_interface_id', $network_interface['NetworkInterfaceId']);

    // Skip if $entity already exists, by updating 'refreshed' time.
    if (!empty($entity_id)) {
      /* @var \Drupal\aws_cloud\Entity\Ec2\NetworkInterface $entity */
      $entity = NetworkInterface::load($entity_id);
      $entity->setName($name);
      $entity->setRefreshed($timestamp);
      $entity->setPrimaryPrivateIp($primary_private_ip);
      $entity->setSecondaryPrivateIp($secondary_private_ip);
      $entity->setAssociationId($primary_association_id);
      $entity->setSecondaryAssociationId($secondary_association_id);
      if ($public_ips != NULL) {
        $public_ips = implode(', ', $public_ips);
      }

      $entity->setPublicIps($public_ips);
      $entity->setVpcId($network_interface['VpcId']);
      $entity->setStatus($network_interface['Status']);

      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
      $entity->save();
    }
    else {
      $entity = NetworkInterface::create([
        'cloud_context' => $cloud_context,
        'name' => $network_interface['NetworkInterfaceId'],
        'network_interface_id' => $network_interface['NetworkInterfaceId'],
        'vpc_id' => $network_interface['VpcId'],
        'mac_address' => $network_interface['MacAddress'],
        'security_groups' => implode(', ', $security_groups),
        'status' => $network_interface['Status'],
        'private_dns' => $network_interface['PrivateDnsName'],
        'primary_private_ip' => $primary_private_ip,
        'secondary_private_ips' => $secondary_private_ip,
        'attachment_id' => $network_interface['Attachment']['AttachmentId'],
        'attachment_owner' => $network_interface['Attachment']['InstanceOwnerId'],
        'attachment_status' => $network_interface['Attachment']['Status'],
        'account_id' => $network_interface['OwnerId'],
        'association_id' => $primary_association_id,
        'secondary_association_id' => $secondary_association_id,
        'subnet_id' => $network_interface['SubnetId'],
        'description' => $network_interface['Description'],
        'public_ips' => $public_ips,
        'source_dest_check' => $network_interface['SourceDestCheck'],
        'instance_id' => $network_interface['Attachment']['InstanceId'],
        'device_index' => $network_interface['Attachment']['DeviceIndex'],
        'delete_on_termination' => $network_interface['Attachment']['DeleteOnTermination'],
        'allocation_id' => $network_interface['Association']['AllocationId'],
        'created' => $timestamp,
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
      $entity->save();
    }
  }

  /**
   * Update or create an Elastic IP entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $elastic_ip
   *   The Elastic IP array.
   */
  public static function updateElasticIp($cloud_context, array $elastic_ip) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);
    $timestamp = time();

    $elastic_ip_name = '';

    $name = $ec2Service->getTagName($elastic_ip, $elastic_ip['PublicIp']);
    $uid = $ec2Service->getUidTagValue($elastic_ip, ElasticIp::TAG_CREATED_BY_UID);
    $entity_id = $ec2Service->getEntityId('aws_cloud_elastic_ip', 'public_ip', $elastic_ip['PublicIp']);

    // Skip if $entity already exists, by updating 'refreshed' time.
    if (!empty($entity_id)) {
      $entity = ElasticIp::load($entity_id);

      // Update fields.
      $entity->setName($name);
      $entity->setInstanceId(!empty($elastic_ip['InstanceId']) ? $elastic_ip['InstanceId'] : '');
      $entity->setNetworkInterfaceId(!empty($elastic_ip['NetworkInterfaceId']) ? $elastic_ip['NetworkInterfaceId'] : '');
      $entity->setPrivateIpAddress(!empty($elastic_ip['PrivateIpAddress']) ? $elastic_ip['PrivateIpAddress'] : '');
      $entity->setNetworkInterfaceOwner(!empty($elastic_ip['NetworkInterfaceOwnerId']) ? $elastic_ip['NetworkInterfaceOwnerId'] : '');
      $entity->setAllocationId(!empty($elastic_ip['AllocationId']) ? $elastic_ip['AllocationId'] : '');
      $entity->setAssociationId(!empty($elastic_ip['AssociationId']) ? $elastic_ip['AssociationId'] : '');
      $entity->setDomain(!empty($elastic_ip['Domain']) ? $elastic_ip['Domain'] : '');

      $entity->setRefreshed($timestamp);

      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
      $entity->save();
    }
    else {
      $entity = ElasticIp::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'public_ip' => $elastic_ip['PublicIp'],
        'instance_id' => !empty($elastic_ip['InstanceId']) ? $elastic_ip['InstanceId'] : '',
        'network_interface_id' => !empty($elastic_ip['NetworkInterfaceId']) ? $elastic_ip['NetworkInterfaceId'] : '',
        'private_ip_address' => !empty($elastic_ip['PrivateIpAddress']) ? $elastic_ip['PrivateIpAddress'] : '',
        'network_interface_owner' => !empty($elastic_ip['NetworkInterfaceOwnerId']) ? $elastic_ip['NetworkInterfaceOwnerId'] : '',
        'allocation_id' => !empty($elastic_ip['AllocationId']) ? $elastic_ip['AllocationId'] : '',
        'association_id' => !empty($elastic_ip['AssociationId']) ? $elastic_ip['AssociationId'] : '',
        'domain' => !empty($elastic_ip['Domain']) ? $elastic_ip['Domain'] : '',
        'created' => $timestamp,
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
      $entity->save();
    }
  }

  /**
   * Update or create a key pair entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $key_pair
   *   The key_pair array.
   */
  public static function updateKeyPair($cloud_context, array $key_pair) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);
    $timestamp = time();

    $entity_id = $ec2Service->getEntityId('aws_cloud_key_pair', 'key_pair_name', $key_pair['KeyName']);

    if (!empty($entity_id)) {
      $entity = KeyPair::load($entity_id);
      $entity->setRefreshed($timestamp);
      $entity->save();
    }
    else {
      $entity = KeyPair::create([
        'cloud_context' => $cloud_context,
        'key_pair_name' => $key_pair['KeyName'],
        'key_fingerprint' => $key_pair['KeyFingerprint'],
        'created' => $timestamp,
        'changed' => $timestamp,
        'refreshed' => $timestamp,
      ]);
      $entity->save();
    }
  }

  /**
   * Update or create a snapshot entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $snapshot
   *   The snapshot array.
   */
  public static function updateSnapshot($cloud_context, array $snapshot) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $ec2Service->getTagName($snapshot, $snapshot['SnapshotId']);
    $entity_id = $ec2Service->getEntityId('aws_cloud_snapshot', 'snapshot_id', $snapshot['SnapshotId']);
    $uid = $ec2Service->getUidTagValue($snapshot, Snapshot::TAG_CREATED_BY_UID);

    if (!empty($entity_id)) {
      $entity = Snapshot::load($entity_id);
      $entity->setName($name);
      $entity->setStatus($snapshot['State']);
      $entity->setRefreshed($timestamp);
      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
      $entity->setCreated(strtotime($snapshot['StartTime']));
      $entity->save();
    }
    else {
      $entity = Snapshot::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'snapshot_id' => $snapshot['SnapshotId'],
        'size' => $snapshot['VolumeSize'],
        'description' => $snapshot['Description'],
        'status' => $snapshot['State'],
        'volume_id' => $snapshot['VolumeId'],
        'progress' => $snapshot['Progress'],
        'encrypted' => $snapshot['Encrypted'] == FALSE ? 'Not Encrypted' : 'Encrypted',
        'kms_key_id' => $snapshot['KmsKeyId'],
        'account_id' => $snapshot['OwnerId'],
        'owner_aliases' => $snapshot['OwnerAlias'],
        'state_message' => $snapshot['StateMessage'],
        'created' => strtotime($snapshot['StartTime']),
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
      $entity->save();
    }
  }

  /**
   * Update or create a VPC entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $vpc
   *   The VPC array.
   */
  public static function updateVpc($cloud_context, array $vpc) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $ec2Service->getTagName($vpc, $vpc['VpcId']);
    $entity_id = $ec2Service->getEntityId('aws_cloud_vpc', 'vpc_id', $vpc['VpcId']);
    $uid = $ec2Service->getUidTagValue($vpc, Vpc::TAG_CREATED_BY_UID);

    // Tags.
    $tags = [];
    if (!isset($vpc['Tags'])) {
      $vpc['Tags'] = [];
    }
    foreach ($vpc['Tags'] ?: [] as $tag) {
      $tags[] = ['tag_key' => $tag['Key'], 'tag_value' => $tag['Value']];
    }

    usort($tags, function ($a, $b) {
      if ($a['tag_key'] == 'Name') {
        return -1;
      }

      if ($b['tag_key'] == 'Name') {
        return 1;
      }

      return strcmp($a['tag_key'], $b['tag_key']);
    });

    // CIDR blocks.
    $cidr_blocks = [];
    if (!isset($vpc['CidrBlockAssociationSet'])) {
      $vpc['CidrBlockAssociationSet'] = [];
    }
    foreach ($vpc['CidrBlockAssociationSet'] ?: [] as $cidr_block) {
      if ($cidr_block['CidrBlockState']['State'] != 'associated') {
        continue;
      }

      $cidr_blocks[] = [
        'cidr' => $cidr_block['CidrBlock'],
        'state' => $cidr_block['CidrBlockState']['State'],
        'status_message' => isset($cidr_block['CidrBlockState']['StatusMessage'])
        ? $cidr_block['CidrBlock']['Status_message']
        : '',
        'association_id' => $cidr_block['AssociationId'],
      ];
    }

    // IPv6 CIDR blocks.
    $ipv6_cidr_blocks = [];
    if (!isset($vpc['Ipv6CidrBlockAssociationSet'])) {
      $vpc['Ipv6CidrBlockAssociationSet'] = [];
    }
    foreach ($vpc['Ipv6CidrBlockAssociationSet'] ?: [] as $ipv6_cidr_block) {
      if ($ipv6_cidr_block['Ipv6CidrBlockState']['State'] != 'associated') {
        continue;
      }

      $ipv6_cidr_blocks[] = [
        'cidr' => $ipv6_cidr_block['Ipv6CidrBlock'],
        'state' => $ipv6_cidr_block['Ipv6CidrBlockState']['State'],
        'status_message' => isset($ipv6_cidr_block['Ipv6CidrBlockState']['StatusMessage'])
        ? $ipv6_cidr_block['CidrBlock']['Status_message']
        : '',
        'association_id' => $ipv6_cidr_block['AssociationId'],
      ];
    }

    if (!empty($entity_id)) {
      $entity = Vpc::load($entity_id);
      $entity->setName($name);
      $entity->setRefreshed($timestamp);
      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
    }
    else {
      $entity = Vpc::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => $timestamp,
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
    }

    $entity->setCidrBlock($vpc['CidrBlock']);
    $entity->setDhcpOptionsId($vpc['DhcpOptionsId']);
    $entity->setInstanceTenancy($vpc['InstanceTenancy']);
    $entity->setDefault($vpc['IsDefault']);
    $entity->setAccountId(isset($vpc['OwnerId']) ? $vpc['OwnerId'] : NULL);
    $entity->setState($vpc['State']);
    $entity->setVpcId($vpc['VpcId']);
    $entity->setTags($tags);
    $entity->setCidrBlocks($cidr_blocks);
    $entity->setIpv6CidrBlocks($ipv6_cidr_blocks);
    $entity->save();
  }

  /**
   * Update or create a subnet entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $subnet
   *   The subnet array.
   */
  public static function updateSubnet($cloud_context, array $subnet) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $ec2Service->getTagName($subnet, $subnet['SubnetId']);
    $entity_id = $ec2Service->getEntityId('aws_cloud_subnet', 'subnet_id', $subnet['SubnetId']);
    $uid = $ec2Service->getUidTagValue($subnet, Subnet::TAG_CREATED_BY_UID);

    // Tags.
    $tags = [];
    if (!isset($subnet['Tags'])) {
      $subnet['Tags'] = [];
    }
    foreach ($subnet['Tags'] ?: [] as $tag) {
      $tags[] = ['tag_key' => $tag['Key'], 'tag_value' => $tag['Value']];
    }

    usort($tags, function ($a, $b) {
      if ($a['tag_key'] == 'Name') {
        return -1;
      }

      if ($b['tag_key'] == 'Name') {
        return 1;
      }

      return strcmp($a['tag_key'], $b['tag_key']);
    });

    if (!empty($entity_id)) {
      $entity = Subnet::load($entity_id);
      $entity->setName($name);
      $entity->setRefreshed($timestamp);
      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
    }
    else {
      $entity = Subnet::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => $timestamp,
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
    }

    $entity->setCidrBlock($subnet['CidrBlock']);
    $entity->setAccountId(isset($subnet['OwnerId']) ? $subnet['OwnerId'] : NULL);
    $entity->setState($subnet['State']);
    $entity->setSubnetId($subnet['SubnetId']);
    $entity->setVpcId($subnet['VpcId']);
    $entity->setTags($tags);
    $entity->save();
  }

  /**
   * Update or create a volume entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $volume
   *   The volume array.
   * @param array $snapshot_id_name_map
   *   The snapshot map.
   */
  public static function updateVolume($cloud_context, array $volume, array $snapshot_id_name_map) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2Service = \Drupal::service('aws_cloud.ec2');
    $ec2Service->setCloudContext($cloud_context);

    $timestamp = time();

    $attachments = [];
    foreach ($volume['Attachments'] ?: [] as $attachment) {
      $attachments[] = $attachment['InstanceId'];
    }

    $name = $ec2Service->getTagName($volume, $volume['VolumeId']);
    $entity_id = $ec2Service->getEntityId('aws_cloud_volume', 'volume_id', $volume['VolumeId']);
    $uid = $ec2Service->getUidTagValue($volume, Volume::TAG_CREATED_BY_UID);

    if ($uid == 0) {
      // Inherit the volume uid from the instance that launched it.
      if (count($attachments)) {
        $uid = $ec2Service->getInstanceUid($attachments[0]);
      }
    }

    // Skip if $entity already exists, by updating 'refreshed' time.
    if (!empty($entity_id)) {
      /* @var \Drupal\aws_cloud\Entity\Ec2\Volume $entity */
      $entity = Volume::load($entity_id);
      $entity->setName($name);
      $entity->setRefreshed($timestamp);
      $entity->setState($volume['State']);
      $entity->setAttachmentInformation(implode(', ', $attachments));
      $entity->setCreated(strtotime($volume['CreateTime']));
      $entity->setSnapshotId($volume['SnapshotId']);
      $entity->setSnapshotName(empty($volume['SnapshotId'])
        ? ''
        : $snapshot_id_name_map[$volume['SnapshotId']]);
      $entity->setSize($volume['Size']);
      $entity->setVolumeType($volume['VolumeType']);
      $entity->setIops($volume['Iops']);

      if ($uid != 0) {
        $entity->setOwnerById($uid);
      }
      $entity->save();
    }
    else {
      $entity = Volume::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'volume_id' => $volume['VolumeId'],
        'size' => $volume['Size'],
        'state' => $volume['State'],
        'volume_status' => $volume['VirtualizationType'],
        'attachment_information' => implode(', ', $attachments),
        'volume_type' => $volume['VolumeType'],
        'iops' => $volume['Iops'],
        'snapshot_id' => $volume['SnapshotId'],
        'snapshot_name' => empty($volume['SnapshotId']) ? '' : $snapshot_id_name_map[$volume['SnapshotId']],
        'availability_zone' => $volume['AvailabilityZone'],
        'encrypted' => $volume['Encrypted'],
        'kms_key_id' => $volume['KmsKeyId'],
        'created' => strtotime($volume['CreateTime']),
        'changed' => $timestamp,
        'refreshed' => $timestamp,
        'uid' => $uid,
      ]);
      $entity->save();
    }
  }

  /**
   * Update or create a template entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $template
   *   The launch template array.
   */
  public static function updateCloudServerTemplate($cloud_context, array $template) {
    /* @var \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface */
    $ec2_service = \Drupal::service('aws_cloud.ec2');
    $ec2_service->setCloudContext($cloud_context);
    $timestamp = time();

    $entity_id = $ec2_service->getEntityId(
      'cloud_server_template',
      'name',
      $template['LaunchTemplateName'],
      ['type' => 'aws_cloud']
    );

    // Skip if $entity already exists, by updating 'refreshed' time.
    if (!empty($entity_id)) {
      $entity = CloudServerTemplate::load($entity_id);
    }
    else {
      $entity = CloudServerTemplate::create([
        'cloud_context' => $cloud_context,
        'type' => 'aws_cloud',
        'name' => $template['LaunchTemplateName'],
        'created' => strtotime($template['CreateTime']),
        'changed' => $timestamp,
      ]);
      $entity->save();
    }

    $entity_type_manager = \Drupal::entityTypeManager();
    $entity_storage = $entity_type_manager->getStorage('cloud_server_template');
    $revision_ids = $entity_storage->revisionIds($entity);

    // Get template data.
    $result = $ec2_service->describeLaunchTemplateVersions([
      'LaunchTemplateName' => $template['LaunchTemplateName'],
    ]);
    $versions = array_reverse($result['LaunchTemplateVersions'] ?: []);

    // Update revisions.
    $revision_ids_updated = [];
    foreach ($revision_ids as $revision_id) {
      $version = array_shift($versions);
      if ($version == NULL) {
        break;
      }

      $revision = $entity_storage->loadRevision($revision_id);
      $revision->isDefaultRevision(TRUE);
      self::updateCloudServerTemplateRevision($ec2_service, $revision, $version);
      $revision_ids_updated[] = $revision_id;
    }

    // Remove revisions not updated.
    $revision_ids_not_updated = array_diff($revision_ids, $revision_ids_updated);
    foreach ($revision_ids_not_updated as $revision_id) {
      $entity_storage->deleteRevision($revision_id);
    }

    // Add revisions if there are versions left.
    foreach ($versions as $version) {
      // Create a new revision.
      $revision = $entity;
      $revision->setNewRevision();
      $revision->isDefaultRevision(TRUE);

      self::updateCloudServerTemplateRevision($ec2_service, $revision, $version);
    }
  }

  /**
   * Update the cloud server template revision.
   *
   * @param \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface $ec2_service
   *   AWS Cloud EC2 Service.
   * @param \Drupal\cloud\Entity\CloudServerTemplate $revision
   *   The revision of a cloud server template.
   * @param array $version
   *   The array of a AWS launch template version.
   */
  private static function updateCloudServerTemplateRevision(
    Ec2ServiceInterface $ec2_service,
    CloudServerTemplate $revision,
    array $version
  ) {
    $revision->set('field_version', $version['VersionNumber']);
    $revision->setRevisionLogMessage(isset($version['VersionDescription']) ? $version['VersionDescription'] : '');

    $template_data = $version['LaunchTemplateData'];

    $revision->set('field_instance_type', isset($template_data['InstanceType']) ? $template_data['InstanceType'] : '');
    $revision->set('field_iam_role', isset($template_data['IamInstanceProfile']) ? $template_data['IamInstanceProfile']['Arn'] : '');
    $revision->set('field_kernel_id', isset($template_data['KernelId']) ? $template_data['KernelId'] : '');
    $revision->set('field_ram', isset($template_data['RamdiskId']) ? $template_data['RamdiskId'] : '');
    $revision->set('field_instance_shutdown_behavior', isset($template_data['InstanceInitiatedShutdownBehavior']) ? $template_data['InstanceInitiatedShutdownBehavior'] : '');
    $revision->set('field_termination_protection', empty($template_data['DisableApiTermination']) ? '0' : '1');
    if (isset($template_data['Monitoring'])) {
      $revision->set('field_monitoring', empty($template_data['Monitoring']['Enabled']) ? '0' : '1');
    }
    $revision->set('field_user_data', isset($template_data['UserData']) ? $template_data['UserData'] : '');

    // Image.
    $image_id = NULL;
    if (isset($template_data['ImageId'])) {
      $image_id = $ec2_service->getEntityId(
        'aws_cloud_image',
        'image_id',
        $template_data['ImageId']
      );

      if ($image_id === NULL) {
        // Import the image.
        $ec2_service->updateImagesWithoutBatch([
          'ImageIds' => [$template_data['ImageId']],
        ]);

        // Search image ID once again.
        $image_id = $ec2_service->getEntityId(
          'aws_cloud_image',
          'image_id',
          $template_data['ImageId']
        );
      }
    }
    $revision->set('field_image_id', $image_id);

    // Security groups.
    $security_group_entity_ids = [];
    if (!empty($template_data['SecurityGroupIds'])) {
      foreach ($template_data['SecurityGroupIds'] ?: [] as $group_id) {
        $entity_id = $ec2_service->getEntityId(
          'aws_cloud_security_group',
          'group_id',
          $group_id
        );

        if ($entity_id !== NULL) {
          $security_group_entity_ids[] = $entity_id;
        }
      }
    }
    $revision->set('field_security_group', $security_group_entity_ids);

    // Key pair.
    $key_pair_id = NULL;
    if (isset($template_data['KeyName'])) {
      $key_pair_id = $ec2_service->getEntityId(
        'aws_cloud_key_pair',
        'key_pair_name',
        $template_data['KeyName']
      );
    }
    $revision->set('field_ssh_key', $key_pair_id);

    // Network interface.
    $network_interface_id = NULL;
    if (!empty($template_data['NetworkInterfaces'])) {
      $network_interfaces = $template_data['NetworkInterfaces'];
      $network_interface = array_shift($network_interfaces);

      if (!empty($network_interface['NetworkInterfaceId'])) {
        $network_interface_id = $ec2_service->getEntityId(
          'aws_cloud_network_interface',
          'network_interface_id',
          $network_interface['NetworkInterfaceId']
        );
      }
    }
    $revision->set('field_network', $network_interface_id);

    // Tags.
    $tags = [];
    if (!empty($template_data['TagSpecifications'])
      && !empty($template_data['TagSpecifications'][0]['Tags'])) {

      $tags = $template_data['TagSpecifications'][0]['Tags'];
    }

    $uid = 0;
    foreach ($tags as $tag) {
      $name = $tag['Key'];
      $value = $tag['Value'];
      if (strpos($name, 'cloud_server_template') !== 0) {
        continue;
      }

      if ($name == CloudServerTemplate::TAG_CREATED_BY_UID) {
        $uid = $value;
        continue;
      }

      $field_name = 'field_' . substr($name, strlen('cloud_server_template_'));
      if ($revision->hasField($field_name)) {
        $revision->set($field_name, $value);
      }
    }

    if ($uid != 0) {
      $revision->setOwnerId($uid);
    }

    // Update field_tags.
    $field_tags = [];
    foreach ($tags as $tag) {
      $field_tags[] = ['tag_key' => $tag['Key'], 'tag_value' => $tag['Value']];
    }
    usort($field_tags, function ($a, $b) {
      if (strpos($a['tag_key'], 'cloud_server_template_') === 0) {
        if (strpos($b['tag_key'], 'cloud_server_template_') === 0) {
          return strcmp($a['tag_key'], $b['tag_key']);
        }
        else {
          return -1;
        }
      }
      else {
        if (strpos($b['tag_key'], 'cloud_server_template_') === 0) {
          return 1;
        }
        else {
          return strcmp($a['tag_key'], $b['tag_key']);
        }
      }
    });

    $revision->set('field_tags', $field_tags);
    $revision->setRevisionCreationTime(strtotime($version['CreateTime']));

    $revision->save();
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc