Example #1
0
 public static Allocation start(final VmInstance vm) {
   BootableSet bootSet = Emis.recreateBootableSet(vm);
   return new Allocation(
       vm.getReservationId(),
       vm.getInstanceId(),
       vm.getInstanceUuid(),
       vm.getUserData(),
       vm.getExpiration(),
       vm.lookupPartition(),
       vm.getKeyPair(),
       bootSet,
       vm.getVmType(),
       vm.getNetworkGroups(),
       vm.isUsePrivateAddressing(),
       vm.getMonitoring(),
       vm.getClientToken(),
       vm.getIamInstanceProfileArn(),
       vm.getIamInstanceProfileId(),
       vm.getIamRoleArn());
 }
public class NetworkInfoBroadcaster {
  private static final Logger logger = Logger.getLogger(NetworkInfoBroadcaster.class);

  private static final AtomicLong lastBroadcastTime = new AtomicLong(0L);
  private static final Lock lastBroadcastTimeLock = new ReentrantLock();
  private static final Semaphore activeBroadcastSemaphore = new Semaphore(1);
  private static final EntityCache<VmInstance, NetworkInfoBroadcasts.VmInstanceNetworkView>
      instanceCache =
          new EntityCache<>(
              VmInstance.named(null),
              Restrictions.not(VmInstance.criterion(TORNDOWN.array())),
              Sets.newHashSet("networkGroups"),
              Sets.newHashSet("bootRecord.machineImage", "bootRecord.vmType"),
              TypeMappers.lookup(VmInstance.class, VmInstanceNetworkView.class));
  private static final EntityCache<NetworkGroup, NetworkGroupNetworkView> securityGroupCache =
      new EntityCache<>(
          NetworkGroup.withNaturalId(null),
          TypeMappers.lookup(NetworkGroup.class, NetworkGroupNetworkView.class));
  private static final EntityCache<Vpc, VpcNetworkView> vpcCache =
      new EntityCache<>(
          Vpc.exampleWithOwner(null), TypeMappers.lookup(Vpc.class, VpcNetworkView.class));
  private static final EntityCache<Subnet, SubnetNetworkView> subnetCache =
      new EntityCache<>(
          Subnet.exampleWithOwner(null), TypeMappers.lookup(Subnet.class, SubnetNetworkView.class));
  private static final EntityCache<DhcpOptionSet, DhcpOptionSetNetworkView> dhcpOptionsCache =
      new EntityCache<>(
          DhcpOptionSet.exampleWithOwner(null),
          TypeMappers.lookup(DhcpOptionSet.class, DhcpOptionSetNetworkView.class));
  private static final EntityCache<NetworkAcl, NetworkAclNetworkView> networkAclCache =
      new EntityCache<>(
          NetworkAcl.exampleWithOwner(null),
          TypeMappers.lookup(NetworkAcl.class, NetworkAclNetworkView.class));
  private static final EntityCache<RouteTable, RouteTableNetworkView> routeTableCache =
      new EntityCache<>(
          RouteTable.exampleWithOwner(null),
          TypeMappers.lookup(RouteTable.class, RouteTableNetworkView.class));
  private static final EntityCache<InternetGateway, InternetGatewayNetworkView>
      internetGatewayCache =
          new EntityCache<>(
              InternetGateway.exampleWithOwner(null),
              TypeMappers.lookup(InternetGateway.class, InternetGatewayNetworkView.class));
  private static final EntityCache<NetworkInterface, NetworkInterfaceNetworkView>
      networkInterfaceCache =
          new EntityCache<>(
              NetworkInterface.exampleWithOwner(null),
              TypeMappers.lookup(NetworkInterface.class, NetworkInterfaceNetworkView.class));
  private static final EntityCache<NatGateway, NatGatewayNetworkView> natGatewayCache =
      new EntityCache<>(
          NatGateway.exampleWithOwner(null),
          TypeMappers.lookup(NatGateway.class, NatGatewayNetworkView.class));
  private static final VpcRouteStateInvalidator vpcRouteStateInvalidator =
      new EventFiringVpcRouteStateInvalidator();

  private static NetworkInfoSource cacheSource() {
    final Supplier<Iterable<VmInstanceNetworkView>> instanceSupplier =
        Suppliers.memoize(instanceCache);
    final Supplier<Iterable<NetworkGroupNetworkView>> securityGroupSupplier =
        Suppliers.memoize(securityGroupCache);
    final Supplier<Iterable<VpcNetworkView>> vpcSupplier = Suppliers.memoize(vpcCache);
    final Supplier<Iterable<SubnetNetworkView>> subnetSupplier = Suppliers.memoize(subnetCache);
    final Supplier<Iterable<DhcpOptionSetNetworkView>> dhcpOptionsSupplier =
        Suppliers.memoize(dhcpOptionsCache);
    final Supplier<Iterable<NetworkAclNetworkView>> networkAclSupplier =
        Suppliers.memoize(networkAclCache);
    final Supplier<Iterable<RouteTableNetworkView>> routeTableSupplier =
        Suppliers.memoize(routeTableCache);
    final Supplier<Iterable<InternetGatewayNetworkView>> internetGatewaySupplier =
        Suppliers.memoize(internetGatewayCache);
    final Supplier<Iterable<NetworkInterfaceNetworkView>> networkInterfaceSupplier =
        Suppliers.memoize(networkInterfaceCache);
    final Supplier<Iterable<NatGatewayNetworkView>> natGatewaySupplier =
        Suppliers.memoize(natGatewayCache);
    return new NetworkInfoSource() {
      @Override
      public Iterable<VmInstanceNetworkView> getInstances() {
        return instanceSupplier.get();
      }

      @Override
      public Iterable<NetworkGroupNetworkView> getSecurityGroups() {
        return securityGroupSupplier.get();
      }

      @Override
      public Iterable<VpcNetworkView> getVpcs() {
        return vpcSupplier.get();
      }

      @Override
      public Iterable<SubnetNetworkView> getSubnets() {
        return subnetSupplier.get();
      }

      @Override
      public Iterable<DhcpOptionSetNetworkView> getDhcpOptionSets() {
        return dhcpOptionsSupplier.get();
      }

      @Override
      public Iterable<NetworkAclNetworkView> getNetworkAcls() {
        return networkAclSupplier.get();
      }

      @Override
      public Iterable<RouteTableNetworkView> getRouteTables() {
        return routeTableSupplier.get();
      }

      @Override
      public Iterable<InternetGatewayNetworkView> getInternetGateways() {
        return internetGatewaySupplier.get();
      }

      @Override
      public Iterable<NetworkInterfaceNetworkView> getNetworkInterfaces() {
        return networkInterfaceSupplier.get();
      }

      @Override
      public Iterable<NatGatewayNetworkView> getNatGateways() {
        return natGatewaySupplier.get();
      }

      @Override
      public Map<String, Iterable<? extends VersionedNetworkView>> getView() {
        return ImmutableMap.<String, Iterable<? extends VersionedNetworkView>>builder()
            .put("instance", getInstances())
            .put("security-group", getSecurityGroups())
            .put("vpc", getVpcs())
            .put("subnet", getSubnets())
            .put("dhcp-option-set", getDhcpOptionSets())
            .put("network-acl", getNetworkAcls())
            .put("route-table", getRouteTables())
            .put("internet-gateway", getInternetGateways())
            .put("network-interface", getNetworkInterfaces())
            .put("nat-gateway", getNatGateways())
            .build();
      }
    };
  }

  public static void requestNetworkInfoBroadcast() {
    final long requestedTime = System.currentTimeMillis();
    final Callable<Void> broadcastRequest =
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            boolean shouldBroadcast = false;
            boolean shouldRetryWithDelay = false;
            try (final LockResource lock = LockResource.lock(lastBroadcastTimeLock)) {
              final long currentTime = System.currentTimeMillis();
              final long lastBroadcast = lastBroadcastTime.get();
              if (requestedTime >= lastBroadcast
                  && lastBroadcast + TimeUnit.SECONDS.toMillis(NetworkGroups.MIN_BROADCAST_INTERVAL)
                      < currentTime
                  && activeBroadcastSemaphore.availablePermits() > 0) {
                if (lastBroadcastTime.compareAndSet(lastBroadcast, currentTime)) {
                  shouldBroadcast = true;
                } else { // re-evaluate
                  broadcastTask(this);
                }
              } else if (requestedTime >= lastBroadcastTime.get()) {
                shouldRetryWithDelay = true;
              }
            }
            if (shouldBroadcast) {
              try {
                broadcastNetworkInfo();
              } catch (Exception e) {
                logger.error("Error broadcasting network information", e);
              }
            } else if (shouldRetryWithDelay) {
              Thread.sleep(100); // pause and re-evaluate to allow for min time between broadcasts
              broadcastTask(this);
            }
            return null;
          }
        };
    broadcastTask(broadcastRequest);
  }

  private static void broadcastTask(Callable<Void> task) {
    Threads.enqueue(Eucalyptus.class, NetworkInfoBroadcaster.class, 5, task);
  }

  @SuppressWarnings("UnnecessaryQualifiedReference")
  static void broadcastNetworkInfo() {
    try (final SemaphoreResource semaphore = SemaphoreResource.acquire(activeBroadcastSemaphore)) {
      // populate with info directly from configuration
      final Optional<NetworkConfiguration> networkConfiguration =
          NetworkConfigurations.getNetworkConfiguration();
      final List<com.eucalyptus.cluster.Cluster> clusters = Clusters.getInstance().listValues();

      final NetworkInfoSource source = cacheSource();
      final Set<String> dirtyPublicAddresses = PublicAddresses.dirtySnapshot();
      final Set<RouteKey> invalidStateRoutes = Sets.newHashSetWithExpectedSize(50);
      final int sourceFingerprint =
          fingerprint(source, clusters, dirtyPublicAddresses, NetworkGroups.NETWORK_CONFIGURATION);
      final NetworkInfo info =
          NetworkInfoBroadcasts.buildNetworkConfiguration(
              networkConfiguration,
              source,
              Suppliers.ofInstance(clusters),
              new Supplier<String>() {
                @Override
                public String get() {
                  return Topology.lookup(Eucalyptus.class).getInetAddress().getHostAddress();
                }
              },
              new Function<List<String>, List<String>>() {
                @Nullable
                @Override
                public List<String> apply(final List<String> defaultServers) {
                  return NetworkConfigurations.loadSystemNameservers(defaultServers);
                }
              },
              dirtyPublicAddresses,
              invalidStateRoutes);
      info.setVersion(
          BaseEncoding.base16().lowerCase().encode(Ints.toByteArray(sourceFingerprint)));

      if (!invalidStateRoutes.isEmpty()) {
        vpcRouteStateInvalidator.accept(invalidStateRoutes);
      }

      Applicators.apply(clusters, info);

    } catch (ApplicatorException e) {
      logger.error("Error during network broadcast", e);
    }
  }

  private static int fingerprint(
      final NetworkInfoSource source,
      final List<com.eucalyptus.cluster.Cluster> clusters,
      final Set<String> dirtyPublicAddresses,
      final String networkConfiguration) {
    final HashFunction hashFunction = goodFastHash(32);
    final Hasher hasher = hashFunction.newHasher();
    final Funnel<VersionedNetworkView> versionedItemFunnel =
        new Funnel<VersionedNetworkView>() {
          @Override
          public void funnel(final VersionedNetworkView o, final PrimitiveSink primitiveSink) {
            primitiveSink.putString(o.getId(), StandardCharsets.UTF_8);
            primitiveSink.putChar('=');
            primitiveSink.putInt(o.getVersion());
          }
        };
    for (final Map.Entry<String, Iterable<? extends VersionedNetworkView>> entry :
        source.getView().entrySet()) {
      hasher.putString(entry.getKey(), StandardCharsets.UTF_8);
      for (final VersionedNetworkView item : entry.getValue()) {
        hasher.putObject(item, versionedItemFunnel);
      }
    }
    hasher.putString(
        Joiner.on(',').join(Sets.newTreeSet(Iterables.transform(clusters, HasName.GET_NAME))),
        StandardCharsets.UTF_8);
    hasher.putString(
        Joiner.on(',').join(Sets.newTreeSet(dirtyPublicAddresses)), StandardCharsets.UTF_8);
    hasher.putInt(networkConfiguration.hashCode());
    return hasher.hash().asInt();
  }

  public static class NetworkInfoBroadcasterEventListener implements EventListener<ClockTick> {
    private final int intervalTicks = 3;
    private volatile int counter = 0;

    public static void register() {
      Listeners.register(ClockTick.class, new NetworkInfoBroadcasterEventListener());
    }

    @SuppressWarnings("UnnecessaryQualifiedReference")
    @Override
    public void fireEvent(final ClockTick event) {
      if (counter++ % intervalTicks == 0
          && Topology.isEnabledLocally(Eucalyptus.class)
          && Hosts.isCoordinator()
          && Bootstrap.isOperational()
          && !Databases.isVolatile()) {
        requestNetworkInfoBroadcast();
      }
    }
  }
}