Exemplo n.º 1
0
Future<Option<ContainerLaunchInfo>> PosixFilesystemIsolatorProcess::prepare(
    const ContainerID& containerId,
    const ContainerConfig& containerConfig)
{
  if (infos.contains(containerId)) {
    return Failure("Container has already been prepared");
  }

  const ExecutorInfo& executorInfo = containerConfig.executorinfo();

  if (executorInfo.has_container()) {
    CHECK_EQ(executorInfo.container().type(), ContainerInfo::MESOS);

    // Return failure if the container change the filesystem root
    // because the symlinks will become invalid in the new root.
    if (executorInfo.container().mesos().has_image()) {
      return Failure("Container root filesystems not supported");
    }

    if (executorInfo.container().volumes().size() > 0) {
      return Failure("Volumes in ContainerInfo is not supported");
    }
  }

  infos.put(containerId, Owned<Info>(new Info(containerConfig.directory())));

  return update(containerId, executorInfo.resources())
      .then([]() -> Future<Option<ContainerLaunchInfo>> { return None(); });
}
Exemplo n.º 2
0
Future<Option<ContainerLaunchInfo>> CgroupsNetClsIsolatorProcess::prepare(
    const ContainerID& containerId,
    const ContainerConfig& containerConfig)
{
  if (infos.contains(containerId)) {
    return Failure("Container has already been prepared");
  }

  // Use this info to create the cgroup, but do not insert it into
  // infos till the cgroup has been created successfully.
  Info info(path::join(flags.cgroups_root, containerId.value()));

  // Create a cgroup for this container.
  Try<bool> exists = cgroups::exists(hierarchy, info.cgroup);
  if (exists.isError()) {
    return Failure("Failed to check if the cgroup already exists: " +
                   exists.error());
  } else if (exists.get()) {
    return Failure("The cgroup already exists");
  }

  Try<Nothing> create = cgroups::create(hierarchy, info.cgroup);
  if (create.isError()) {
    return Failure("Failed to create the cgroup: " + create.error());
  }

  // 'chown' the cgroup so the executor can create nested cgroups. Do
  // not recurse so the control files are still owned by the slave
  // user and thus cannot be changed by the executor.
  if (containerConfig.has_user()) {
    Try<Nothing> chown = os::chown(
        containerConfig.user(),
        path::join(hierarchy, info.cgroup),
        false);

    if (chown.isError()) {
      return Failure("Failed to change ownership of cgroup hierarchy: " +
                     chown.error());
    }
  }

  infos.emplace(containerId, info);

  return update(containerId, containerConfig.executorinfo().resources())
    .then([]() -> Future<Option<ContainerLaunchInfo>> {
      return None();
    });
}
Exemplo n.º 3
0
process::Future<Option<ContainerLaunchInfo>> NetworkIsolatorProcess::prepare(
    const ContainerID& containerId,
    const ContainerConfig& containerConfig)
{
  LOG(INFO) << "NetworkIsolator::prepare for container: " << containerId;

  const ExecutorInfo executorInfo = containerConfig.executorinfo();
  if (!executorInfo.has_container()) {
    LOG(INFO) << "NetworkIsolator::prepare Ignoring request as "
              << "executorInfo.container is missing for container: "
              << containerId;
    return None();
  }

  if (executorInfo.container().network_infos().size() == 0) {
    LOG(INFO) << "NetworkIsolator::prepare Ignoring request as "
              << "executorInfo.container.network_infos is missing for "
              << "container: " << containerId;
    return None();
  }

  if (executorInfo.container().network_infos().size() > 1) {
    return Failure(
        "NetworkIsolator:: multiple NetworkInfos are not supported.");
  }

  NetworkInfo networkInfo = executorInfo.container().network_infos(0);

  if (networkInfo.has_protocol()) {
    return Failure(
      "NetworkIsolator: NetworkInfo.protocol is deprecated and unsupported.");
  }
  if (networkInfo.has_ip_address()) {
    return Failure(
      "NetworkIsolator: NetworkInfo.ip_address is deprecated and"
      " unsupported.");
  }

  string uid = UUID::random().toString();

  // Two IPAM commands:
  // 1) reserve for IPs the user has specifically asked for.
  // 2) auto-assign IPs.
  // Spin through all IPAddress messages once to get info for each command.
  // Then we'll issue each command if needed.
  IPAMReserveIPMessage reserveMessage;
  IPAMReserveIPMessage::Args* reserveArgs = reserveMessage.mutable_args();

  // Counter of IPs to auto assign.
  int numIPv4 = 0;
  foreach (const NetworkInfo::IPAddress& ipAddress, networkInfo.ip_addresses()) {
    if (ipAddress.has_ip_address() && ipAddress.has_protocol()) {
      return Failure("NetworkIsolator: Cannot include both ip_address and "
                     "protocol in a request.");
    }
    if (ipAddress.has_ip_address()) {
      // Store IP to attempt to reserve.
      reserveArgs->add_ipv4_addrs(ipAddress.ip_address());
    } else if (ipAddress.has_protocol() &&
               ipAddress.protocol() == NetworkInfo::IPv6){
      return Failure("NetworkIsolator: IPv6 is not supported at this time.");
    } else {
      // Either protocol is IPv4, or not included (in which case we default to
      // IPv4 anyway).
      numIPv4++;
    }
  }

  if (!(reserveArgs->ipv4_addrs_size() + numIPv4)) {
    return Failure(
      "NetworkIsolator: Container requires at least one IP address.");
  }

  // All the IP addresses, both reserved and allocated.
  vector<string> allAddresses;

  // Reserve provided IPs first.
  if (reserveArgs->ipv4_addrs_size()) {
    reserveArgs->set_hostname(slaveInfo.hostname());
    reserveArgs->set_uid(uid);
    reserveArgs->mutable_netgroups()->CopyFrom(networkInfo.groups());

    LOG(INFO) << "Sending IP reserve command to IPAM";
    Try<IPAMResponse> response =
      runCommand<IPAMReserveIPMessage, IPAMResponse>(
          ipamClientPath, reserveMessage);
    if (response.isError()) {
      return Failure("Error reserving IPs with IPAM: " + response.error());
    }

    string addresses = "";
    foreach (const string& addr, reserveArgs->ipv4_addrs()) {
      addresses = addresses + addr + " ";
      allAddresses.push_back(addr);
    }
    LOG(INFO) << "IP(s) " << addresses << "reserved with IPAM";
  }