Search in sources :

Example 16 with TagChanges

use of org.platformlayer.core.model.TagChanges in project platformlayer by platformlayer.

the class LxcInstanceController method addChildren.

@Override
protected void addChildren() throws OpsException {
    final DirectInstance model = OpsContext.get().getInstance(DirectInstance.class);
    CloudInstanceMapper instance;
    {
        instance = injected(CloudInstanceMapper.class);
        instance.instance = OpsContext.get().getInstance(DirectInstance.class);
        addChild(instance);
    }
    instance.addChild(ManagedDirectory.build(getInstanceDir(), "700"));
    // TODO: If we're not going to assign an IPV4 redirect, we might not need this
    final Provider<AddressModel> address4;
    {
        NetworkAddressPoolAssignment provider = instance.addChild(NetworkAddressPoolAssignment.class);
        provider.holder = model.getKey();
        provider.poolProvider = DirectCloudUtils.getPrivateAddressPool4();
        address4 = provider;
    }
    final Provider<AddressModel> address6;
    {
        NetworkAddressPoolAssignment provider = instance.addChild(NetworkAddressPoolAssignment.class);
        provider.holder = model.getKey();
        provider.poolProvider = directCloudHelpers.getAddressPool6();
        address6 = provider;
    }
    // {
    // NetworkTunDevice tun = injected(NetworkTunDevice.class);
    // tun.interfaceName = getEthernetDeviceName();
    // tun.bridgeName = Providers.getProperty(assignNetworkAddress, "bridge");
    // instance.addChild(tun);
    // }
    {
        DownloadImage download = injected(DownloadImage.class);
        download.imageFile = new File(getInstanceDir(), "rootfs");
        download.recipeKey = model.recipeId;
        download.imageFormats = Collections.singletonList(ImageFormat.Tar);
        instance.addChild(download);
    }
    {
        LxcBootstrap bootstrap = injected(LxcBootstrap.class);
        bootstrap.address4 = address4;
        bootstrap.address6 = address6;
        bootstrap.lxcId = id;
        bootstrap.instanceDir = instanceDir;
        try {
            bootstrap.sshPublicKey = OpenSshUtils.readSshPublicKey(model.sshPublicKey);
        } catch (IOException e) {
            throw new OpsException("Error deserializing SSH key", e);
        }
        bootstrap.hostname = model.hostname;
        instance.addChild(bootstrap);
    }
    InstanceScript script;
    {
        script = instance.addChild(InstanceScript.class);
        script.filePath = new File(DirectHostController.LXC_INSTANCE_DIR, id);
        String key = "lxc-" + id;
        script.key = key;
        script.addresses.add(address4);
        script.addresses.add(address6);
        // script.hostPrimaryInterface = hostModel.publicInterface;
        Command command = Command.build("lxc-start");
        command.addLiteral("--name").addQuoted(id);
        script.launchInstanceCommand = command;
    }
    {
        // ManagedSupervisordInstance service = instance.addChild(ManagedSupervisordInstance.class);
        StandardService service = instance.addChild(StandardService.class);
        script.configure(model, service);
    }
    {
        OpsProvider<TagChanges> tagChanges = new OpsProvider<TagChanges>() {

            @Override
            public TagChanges get() {
                TagChanges tagChanges = new TagChanges();
                tagChanges.addTags.add(Tag.INSTANCE_KEY.build(model.getKey()));
                AddressModel ipv4 = address4.get();
                AddressModel ipv6 = address6.get();
                if (ipv4 != null) {
                    tagChanges.addTags.add(Tag.NETWORK_ADDRESS.build(ipv4));
                }
                if (ipv6 != null) {
                    tagChanges.addTags.add(Tag.NETWORK_ADDRESS.build(ipv6));
                }
                return tagChanges;
            }
        };
        instance.addChild(Tagger.build(model, tagChanges));
    }
}
Also used : NetworkAddressPoolAssignment(org.platformlayer.ops.pool.NetworkAddressPoolAssignment) OpsException(org.platformlayer.ops.OpsException) DirectInstance(org.platformlayer.service.cloud.direct.model.DirectInstance) InstanceScript(org.platformlayer.service.cloud.direct.ops.InstanceScript) StandardService(org.platformlayer.ops.supervisor.StandardService) IOException(java.io.IOException) TagChanges(org.platformlayer.core.model.TagChanges) CloudInstanceMapper(org.platformlayer.service.cloud.direct.ops.CloudInstanceMapper) OpsProvider(org.platformlayer.ops.OpsProvider) Command(org.platformlayer.ops.Command) AddressModel(org.platformlayer.core.model.AddressModel) File(java.io.File) DownloadImage(org.platformlayer.service.cloud.direct.ops.DownloadImage)

Example 17 with TagChanges

use of org.platformlayer.core.model.TagChanges in project platformlayer by platformlayer.

the class KvmInstance method addChildren.

@Override
protected void addChildren() throws OpsException {
    CloudInstanceMapper instance;
    {
        instance = injected(CloudInstanceMapper.class);
        instance.instance = OpsContext.get().getInstance(DirectInstance.class);
        addChild(instance);
    }
    instance.addChild(ManagedDirectory.build(getInstanceDir(), "700"));
    final NetworkAddressPoolAssignment address4;
    {
        address4 = instance.addChild(NetworkAddressPoolAssignment.class);
        address4.holder = owner;
        address4.poolProvider = DirectCloudUtils.getPrivateAddressPool4();
    }
    final NetworkAddressPoolAssignment address6;
    {
        address6 = instance.addChild(NetworkAddressPoolAssignment.class);
        address6.holder = owner;
        address6.poolProvider = directCloudHelpers.getAddressPool6();
    }
    {
        NetworkTunDevice tun = injected(NetworkTunDevice.class);
        tun.interfaceName = getEthernetDeviceName();
        tun.bridgeName = new Provider<String>() {

            @Override
            public String get() {
                DirectHost host = OpsContext.get().getInstance(DirectHost.class);
                return host.bridge;
            }
        };
        instance.addChild(tun);
    }
    final SocketAddressPoolAssignment assignMonitorPort;
    {
        assignMonitorPort = injected(SocketAddressPoolAssignment.class);
        assignMonitorPort.holder = owner;
        assignMonitorPort.poolProvider = DirectCloudUtils.getKvmMonitorPortPool();
        instance.addChild(assignMonitorPort);
    }
    final SocketAddressPoolAssignment assignVncPort;
    {
        assignVncPort = injected(SocketAddressPoolAssignment.class);
        assignVncPort.holder = owner;
        assignVncPort.poolProvider = DirectCloudUtils.getVncPortPool();
        instance.addChild(assignVncPort);
    }
    {
        ConfigIso iso = injected(ConfigIso.class);
        iso.isoFile = getConfigIsoPath();
        iso.buildDir = new File(getInstanceDir(), "config_iso_src");
        iso.model = new TemplateDataSource() {

            @Override
            public void buildTemplateModel(Map<String, Object> model) throws OpsException {
                InterfaceModel eth0 = InterfaceModel.build("eth0");
                AddressModel ipv4 = address4.get();
                eth0.addAddress(ipv4);
                AddressModel ipv6 = address6.get();
                eth0.addAddress(ipv6);
                List<InterfaceModel> interfaces = Lists.newArrayList();
                interfaces.add(eth0);
                model.put("interfaces", interfaces);
                List<String> authorizedKeys = Lists.newArrayList();
                authorizedKeys.add(OpenSshUtils.serialize(sshPublicKey));
                model.put("authorizedKeys", authorizedKeys);
            }
        };
        instance.addChild(iso);
    }
    {
        DownloadImage download = injected(DownloadImage.class);
        download.imageFile = getImagePath();
        download.recipeKey = recipeId;
        download.imageFormats = Arrays.asList(ImageFormat.DiskRaw, ImageFormat.DiskQcow2);
        instance.addChild(download);
    }
    {
        ManagedKvmInstance kvmInstance = addChild(ManagedKvmInstance.class);
        kvmInstance.id = id;
        kvmInstance.memoryMb = Math.max(256, minimumMemoryMB);
        kvmInstance.vcpus = 1;
        kvmInstance.base = getInstanceDir();
        kvmInstance.monitor = assignMonitorPort;
        kvmInstance.vnc = assignVncPort;
        kvmInstance.nics = buildVnics();
        kvmInstance.drives = buildDrives();
        kvmInstance.addresses.add(address4);
        kvmInstance.addresses.add(address6);
    }
    {
        final DirectInstance model = OpsContext.get().getInstance(DirectInstance.class);
        OpsProvider<TagChanges> tagChanges = new OpsProvider<TagChanges>() {

            @Override
            public TagChanges get() {
                TagChanges tagChanges = new TagChanges();
                tagChanges.addTags.add(Tag.INSTANCE_KEY.build(model.getKey()));
                AddressModel ipv4 = address4.get();
                AddressModel ipv6 = address6.get();
                tagChanges.addTags.add(Tag.NETWORK_ADDRESS.build(ipv4));
                tagChanges.addTags.add(Tag.NETWORK_ADDRESS.build(ipv6));
                return tagChanges;
            }
        };
        addChild(Tagger.build(model, tagChanges));
    }
}
Also used : NetworkAddressPoolAssignment(org.platformlayer.ops.pool.NetworkAddressPoolAssignment) SocketAddressPoolAssignment(org.platformlayer.ops.pool.SocketAddressPoolAssignment) TemplateDataSource(org.platformlayer.ops.templates.TemplateDataSource) DirectInstance(org.platformlayer.service.cloud.direct.model.DirectInstance) TagChanges(org.platformlayer.core.model.TagChanges) OpsProvider(org.platformlayer.ops.OpsProvider) Provider(com.google.inject.Provider) CloudInstanceMapper(org.platformlayer.service.cloud.direct.ops.CloudInstanceMapper) DirectHost(org.platformlayer.service.cloud.direct.model.DirectHost) InterfaceModel(org.platformlayer.ops.networks.InterfaceModel) OpsProvider(org.platformlayer.ops.OpsProvider) AddressModel(org.platformlayer.core.model.AddressModel) File(java.io.File) Map(java.util.Map) DownloadImage(org.platformlayer.service.cloud.direct.ops.DownloadImage)

Example 18 with TagChanges

use of org.platformlayer.core.model.TagChanges in project platformlayer by platformlayer.

the class DirectPublicPorts method addChildren.

@Override
protected void addChildren() throws OpsException {
    final CloudInstanceMapper cloudHost;
    {
        cloudHost = injected(CloudInstanceMapper.class);
        cloudHost.createInstance = false;
        cloudHost.instance = backendItem;
        addChild(cloudHost);
    }
    final SocketAddressPoolAssignment assignPublicAddress;
    {
        assignPublicAddress = cloudHost.addChild(SocketAddressPoolAssignment.class);
        assignPublicAddress.holder = backendItem.getKey();
        if (Objects.equal(transport, Transport.Ipv6)) {
            assignPublicAddress.poolProvider = new OpsProvider<ResourcePool<InetSocketAddress>>() {

                @Override
                public ResourcePool<InetSocketAddress> get() throws OpsException {
                    final ResourcePool<AddressModel> pool = directCloudHelpers.getAddressPool6().get();
                    return new AssignPortToAddressPool(pool, publicPort);
                }
            };
        } else {
            List<Integer> publicPortCluster = this.publicPortCluster;
            if (publicPortCluster == null) {
                publicPortCluster = Lists.newArrayList();
                publicPortCluster.add(publicPort);
            }
            if (!publicPortCluster.contains(publicPort)) {
                throw new OpsException("Port set specified, but public port not in the set");
            }
            assignPublicAddress.poolProvider = directCloudHelpers.getPublicAddressPool4(publicPort, publicPortCluster);
        }
    }
    if (Objects.equal(transport, Transport.Ipv6)) {
        // TODO: Do we need separate frontend / backend ports really?
        if (this.publicPort != this.backendPort) {
            throw new UnsupportedOperationException();
        }
    } else {
        for (Protocol protocol : Protocol.TcpAndUdp()) {
            IptablesForwardPort forward = injected(IptablesForwardPort.class);
            forward.publicAddress = assignPublicAddress;
            forward.ruleKey = protocol.name() + "-" + uuid;
            forward.protocol = protocol;
            forward.privateAddress = new OpsProvider<String>() {

                @Override
                public String get() throws OpsException {
                    // Refresh item to pick up new tags
                    backendItem = platformLayerClient.getItem(backendItem.getKey(), DirectInstance.class);
                    PlatformLayerCloudMachine instanceMachine = (PlatformLayerCloudMachine) instanceHelpers.getMachine(backendItem);
                    DirectInstance instance = (DirectInstance) instanceMachine.getInstance();
                    List<InetAddress> addresses = Tag.NETWORK_ADDRESS.find(instance);
                    InetAddress address = InetAddressChooser.preferIpv4().choose(addresses);
                    if (address == null) {
                        throw new IllegalStateException();
                    }
                    if (InetAddressUtils.isIpv6(address)) {
                        // We can't NAT IPV4 -> IPV6 (I think)
                        throw new IllegalStateException();
                    }
                    return address.getHostAddress();
                }
            };
            forward.privatePort = backendPort;
            cloudHost.addChild(forward);
        }
    }
    {
        OpsProvider<TagChanges> tagChanges = new OpsProvider<TagChanges>() {

            @Override
            public TagChanges get() {
                TagChanges tagChanges = new TagChanges();
                InetSocketAddress socketAddress = assignPublicAddress.get();
                if (socketAddress == null) {
                    return null;
                }
                if (socketAddress.getPort() != publicPort) {
                    throw new IllegalStateException();
                }
                EndpointInfo endpoint = new EndpointInfo(socketAddress);
                tagChanges.addTags.add(endpoint.toTag());
                return tagChanges;
            }
        };
        for (ItemBase tagItem : tagItems) {
            Tagger tagger = addChild(Tagger.class);
            tagger.platformLayerKey = tagItem.getKey();
            tagger.tagChangesProvider = tagChanges;
        }
    }
}
Also used : OpsException(org.platformlayer.ops.OpsException) Tagger(org.platformlayer.ops.tagger.Tagger) SocketAddressPoolAssignment(org.platformlayer.ops.pool.SocketAddressPoolAssignment) ItemBase(org.platformlayer.core.model.ItemBase) InetSocketAddress(java.net.InetSocketAddress) PlatformLayerCloudMachine(org.platformlayer.ops.machines.PlatformLayerCloudMachine) DirectInstance(org.platformlayer.service.cloud.direct.model.DirectInstance) TagChanges(org.platformlayer.core.model.TagChanges) EndpointInfo(org.platformlayer.core.model.EndpointInfo) OpsProvider(org.platformlayer.ops.OpsProvider) AddressModel(org.platformlayer.core.model.AddressModel) List(java.util.List) Protocol(org.platformlayer.ops.firewall.Protocol) IptablesForwardPort(org.platformlayer.ops.firewall.scripts.IptablesForwardPort) InetAddress(java.net.InetAddress)

Example 19 with TagChanges

use of org.platformlayer.core.model.TagChanges in project platformlayer by platformlayer.

the class PlatformlayerBackedPool method assign.

@Override
public T assign(PlatformLayerKey owner, boolean required) throws OpsException {
    T assigned = findAssigned(owner);
    if (assigned != null) {
        return assigned;
    }
    for (int i = 0; i < 10; i++) {
        ItemBase resource = platformLayer.getItem(resourceKey);
        String assignedItem = pickUnassigned(resource);
        if (assignedItem == null) {
            break;
        }
        Assignment assignment = new Assignment(owner.getUrl(), assignedItem, subkey);
        Tag assignmentTag = assignment.asTag();
        TagChanges tagChanges = new TagChanges();
        tagChanges.addTags.add(assignmentTag);
        if (null != platformLayer.changeTags(resourceKey, tagChanges, resource.getVersion())) {
            return adapter.toItem(assignedItem);
        }
        if (!TimeSpan.ONE_SECOND.doSafeSleep()) {
            break;
        }
    }
    if (required) {
        throw new OpsException("Unable to assign value from pool: " + toString());
    }
    return null;
}
Also used : OpsException(org.platformlayer.ops.OpsException) ItemBase(org.platformlayer.core.model.ItemBase) Tag(org.platformlayer.core.model.Tag) TagChanges(org.platformlayer.core.model.TagChanges)

Example 20 with TagChanges

use of org.platformlayer.core.model.TagChanges in project platformlayer by platformlayer.

the class DiskImageController method buildImage.

public void buildImage(DiskImage image) throws OpsException, IOException {
    // Assume the worst...
    opsContext.setFailure(true);
    MachineProvider targetCloud = cloudHelpers.getCloud(image.cloud);
    DiskImageRecipe recipe = platformLayer.getItem(image.recipeId, DiskImageRecipe.class);
    OperatingSystem operatingSystem = getRequestedOperatingSystem(recipe);
    String kernelPackage = packageHelpers.getDefaultKernelPackage(operatingSystem);
    String filesystem = "ext3";
    ImageFormat imageFormat = EnumUtils.valueOfCaseInsensitive(ImageFormat.class, image.format);
    boolean buildTar = imageFormat == ImageFormat.Tar;
    // TODO: This logic is not intrinsically correct
    // boolean supportCloudConfigDisk = imageFormat != ImageFormat.DiskQcow2;
    boolean supportCloudConfigDisk = true;
    boolean useConfigDriveSymlinks = false;
    String configDriveLabel = "config";
    List<String> packages = Lists.newArrayList();
    packages.add("openssh-server");
    // Needed for preseeding
    packages.add("debconf-utils");
    if (operatingSystem.getDistribution() == Distribution.Debian) {
        packages.add("locales");
    }
    // We always want some basics available in our images
    packages.add("curl");
    String hostname = "openstack";
    MachineCreationRequest request = new MachineCreationRequest();
    SshKey sshKey = service.getSshKey();
    // There are problems using LXC with debootstrap
    request.hostPolicy = new HostPolicy();
    request.hostPolicy.allowRunInContainer = false;
    // Null means 'use bootstrap image'
    request.recipeId = null;
    request.sshPublicKey = sshKey.getKeyPair().getPublic();
    request.sshPublicKeyName = service.getSshKeyName();
    request.securityGroups = Lists.newArrayList();
    String securityGroup = service.getSecurityGroupName();
    request.securityGroups.add(securityGroup);
    // We don't need a lot of memory to build a disk image (I think!)
    request.minimumMemoryMB = 256;
    Machine machine = cloud.createInstance(request, image.getKey());
    opsContext.takeOwnership(machine);
    machine = waitForAddress(machine);
    OpsTarget target = machine.getTarget(sshKey);
    waitForTarget(target);
    File tempDir = target.createTempDir();
    apt.update(target, true);
    // We need to install curl first so we can detect the performance of our proxies
    // Needed for proxy testing at least
    apt.install(target, "curl");
    CommandEnvironment httpProxyEnv = httpProxies.getHttpProxyEnvironment(target, Usage.SoftwarePackages, null);
    // For now, we assume that this image doesn't have debootstrap pre-installed
    apt.install(target, "debootstrap");
    // For transferring the file to a direct image server
    // debootstrap with LXC seems to have serious problems...
    boolean supportLxc = false;
    if (supportLxc) {
        apt.install(target, "fakechroot", "fakeroot");
    }
    Command command;
    File rootfsDir;
    File imageFile;
    File loopbackPartition = null;
    if (!buildTar) {
        apt.install(target, "mbr");
        apt.install(target, "parted");
        apt.install(target, "kpartx");
        apt.install(target, "extlinux");
        // Same with qemu-kvm
        // (needed for qemu-img convert ... a lot of extra stuff for just the
        // utils!)
        // packageHelpers.getPackageFor("qemu-img", operatingSystem);
        String qemuImgPackage = "qemu-utils";
        apt.install(target, qemuImgPackage);
        // Use local ephemeral storage...
        imageFile = new File(tempDir, "image.raw");
        command = Command.build("dd if=/dev/null bs=1M seek=8180 of={0}", imageFile);
        target.executeCommand(command);
        // Create partitions
        target.executeCommand(Command.build("parted -s {0} mklabel msdos", imageFile));
        target.executeCommand(Command.build("parted -s {0} mkpart primary 0% 100%", imageFile));
        target.executeCommand(Command.build("parted -s {0} set 1 boot on", imageFile));
        // Install Master Boot Record
        target.executeCommand(Command.build("install-mbr {0}", imageFile));
        // Mount the partitions
        // Hopefully it’s loop0p1...
        target.executeCommand(Command.build("modprobe dm-mod"));
        // boolean isMounted = false;
        // 
        // {
        // ProcessExecution mountExecution = target.executeCommand(Command.build("mount", imageFile));
        // String stdout = mountExecution.getStdOut();
        // System.out.println(stdout);
        // 
        // for (String line : Splitter.on('\n').split(stdout)) {
        // line = line.trim();
        // if (line.isEmpty()) {
        // continue;
        // }
        // 
        // List<String> tokens = Lists.newArrayList(Splitter.on(' ').split(line));
        // if (tokens.size() < 3) {
        // throw new IllegalStateException("Cannot parse mount line: " + line);
        // }
        // 
        // String mountDir = tokens.get(2);
        // if (mountDir.equals(mntDir.getAbsolutePath())) {
        // isMounted = true;
        // loopbackPartition = new File(tokens.get(0));
        // break;
        // }
        // }
        // 
        // // /dev/sda1 on / type ext4 (rw,errors=remount-ro)
        // // tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
        // // proc on /proc type proc (rw,noexec,nosuid,nodev)
        // // sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
        // // udev on /dev type tmpfs (rw,mode=0755)
        // // tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
        // // devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)
        // // /dev/mapper/loop0p1 on /tmp/8389210e66cd0df6/mnt type ext3 (rw)
        // // proc on /tmp/8389210e66cd0df6/mnt/proc type proc (rw)
        // }
        // 
        // if (!isMounted)
        {
            ProcessExecution kpartxExecution = target.executeCommand(Command.build("kpartx -av {0}", imageFile));
            String stdout = kpartxExecution.getStdOut();
            List<String> tokens = Lists.newArrayList(Splitter.on(' ').split(stdout));
            if (tokens.size() != 9) {
                throw new IllegalStateException("Cannot parse kpartx stdout: " + stdout);
            }
            // add map loop6p1 (253:6): 0 16750592 linear /dev/loop6 2048
            String partitionDevice = tokens.get(2);
            if (!partitionDevice.startsWith("loop")) {
                throw new IllegalStateException("kpartx output does not look like a partition: " + stdout);
            }
            loopbackPartition = new File("/dev/mapper/" + partitionDevice);
        }
        // Format filesystem
        command = Command.build("yes | mkfs." + filesystem + " {0}", loopbackPartition);
        command.setTimeout(TimeSpan.FIVE_MINUTES);
        target.executeCommand(command);
        // Get this onto disk now, so we don't delay later commands
        target.executeCommand(Command.build("sync").setTimeout(TimeSpan.FIVE_MINUTES));
        // Don’t force a check based on dates
        target.executeCommand(Command.build("tune2fs -i 0 {0}", loopbackPartition).setTimeout(TimeSpan.FIVE_MINUTES));
        // Get this onto disk now, so we don't delay later commands
        target.executeCommand(Command.build("sync").setTimeout(TimeSpan.FIVE_MINUTES));
        // Mount on mnt/
        File mntDir = new File(tempDir, "mnt");
        target.executeCommand("mkdir {0}", mntDir);
        target.executeCommand(Command.build("mount {0} {1}", loopbackPartition, mntDir).setTimeout(TimeSpan.FIVE_MINUTES));
        rootfsDir = mntDir;
    } else {
        rootfsDir = new File(tempDir, "rootfs");
        imageFile = new File(tempDir, "image.tar.bz2");
    }
    if (buildTar) {
        apt.install(target, "bzip2");
    }
    if (supportLxc) {
        command = Command.build("fakechroot fakeroot debootstrap");
    } else {
        command = Command.build("debootstrap");
    }
    command.addLiteral("--verbose");
    command.addLiteral("--resolve-deps");
    if (supportLxc) {
        // Lxc has problems with mounting etc; fakechroot avoids this
        command.addLiteral("--variant=fakechroot");
    // command.addLiteral("--variant=minbase");
    }
    command.addQuoted("--include=", Joiner.on(",").join(packages));
    command.addLiteral(operatingSystem.getVersion());
    command.addFile(rootfsDir);
    // command.addQuoted(aptSource);
    command.setEnvironment(httpProxyEnv);
    command.setTimeout(TimeSpan.THIRTY_MINUTES);
    try {
        target.executeCommand(command);
    } catch (ProcessExecutionException e) {
        String debootstrapLog = target.readTextFile(new File(rootfsDir, "debootstrap/debootstrap.log"));
        log.warn("Debootstrap log: " + debootstrapLog);
        throw new OpsException("Error running debootstrap", e);
    }
    // TODO: Switch to ChrootOpsTarget, so we can move this stuff into utility functions
    ChrootOpsTarget chrootTarget = new ChrootOpsTarget(rootfsDir, new File("/tmp"), target);
    FileUpload.upload(target, new File(rootfsDir, "etc/hostname"), hostname);
    {
        // Stop services being started in the chroot
        String policy = ResourceUtils.get(getClass(), "usr.sbin.policy-rc.d");
        File policyFile = new File(rootfsDir, "usr/sbin/policy-rc.d");
        FileUpload.upload(target, policyFile, policy);
        target.chmod(policyFile, "755");
    }
    target.executeCommand("mount -t proc proc {0}", new File(rootfsDir, "proc"));
    apt.update(chrootTarget, true);
    target.executeCommand("chroot {0} locale-gen en_US.utf8", rootfsDir);
    target.executeCommand("chroot {0} /bin/bash -c \"DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales\"", rootfsDir);
    if (!buildTar) {
        {
            File kernelImgConf = new File(rootfsDir, "etc/kernel-img.conf");
            String preseedData = ResourceUtils.get(getClass(), "kernel-img.conf");
            FileUpload.upload(target, kernelImgConf, preseedData);
        }
        {
            File preseedTmpDir = target.createTempDir();
            File preseedFile = new File(preseedTmpDir, "kernel.preseed");
            String preseedData = ResourceUtils.get(getClass(), "kernel.preseed");
            FileUpload.upload(target, preseedFile, preseedData);
            target.executeCommand(Command.build("cat {0} | chroot {1} debconf-set-selections", preseedFile, rootfsDir));
            apt.install(chrootTarget, kernelPackage);
        }
    }
    preconfigurePackages(chrootTarget, recipe.configurePackage);
    if (recipe.repositoryKey != null) {
        addRepositoryKeys(chrootTarget, recipe.repositoryKey);
    }
    if (recipe.repository != null) {
        addRepositories(chrootTarget, recipe.repository);
        apt.update(chrootTarget, true);
    }
    if (recipe.addPackage != null) {
        apt.install(chrootTarget, recipe.addPackage);
        if (recipe.addPackage.contains("jenkins")) {
            // It looks like jenkins doesn't honor policy-rc.d (?)
            // TODO: Fix this monstrosity...
            log.warn("Hard-coding service stop after jenkins installation");
            target.executeCommand(Command.build("chroot {0} /etc/init.d/jenkins stop", rootfsDir));
        }
    }
    apt.upgrade(chrootTarget);
    apt.clean(chrootTarget);
    if (!buildTar) {
        String uuid;
        {
            ProcessExecution uuidExecution = target.executeCommand("blkid -o value -s UUID {0}", loopbackPartition);
            uuid = uuidExecution.getStdOut().trim();
        }
        // Set up /etc/fstab
        String fstab = "# /etc/fstab: static file system information.\n";
        // TODO: Swap
        fstab += "proc\t/proc\tproc\tnodev,noexec,nosuid\t0\t0\n";
        // fstab += "/dev/sda1\t/\t" + filesystem +
        // "\terrors=remount-ro\t0\t1\n";
        fstab += String.format("UUID=%s\t/\t%s\terrors=remount-ro\t0\t1\n", uuid, filesystem);
        if (supportCloudConfigDisk) {
            if (useConfigDriveSymlinks) {
                // Use configuration from cloud_config mount
                target.mkdir(new File(rootfsDir, "media/config"));
                fstab += "/dev/disk/by-label/" + configDriveLabel + "\t/media/config\tudf,iso9660\tro\t0\t0\n";
            }
        }
        FileUpload.upload(target, new File(rootfsDir, "etc/fstab"), fstab);
        log.info("fstab = " + fstab);
        // Set up extlinux
        {
            ProcessExecution kernelExecution = target.executeCommand("chroot {0} find boot/ -name \"vmlinuz-*\"", rootfsDir);
            List<String> kernels = Lists.newArrayList();
            for (String kernel : kernelExecution.getStdOut().split("\n")) {
                kernel = kernel.trim();
                if (kernel.isEmpty()) {
                    continue;
                }
                kernels.add(kernel);
            }
            if (kernels.size() > 1) {
                throw new IllegalStateException("Multiple kernels found");
            } else if (kernels.size() != 1) {
                throw new IllegalStateException("No kernels found");
            }
            ProcessExecution initrdExecution = target.executeCommand("chroot {0} find boot/ -name \"initrd*\"", rootfsDir);
            List<String> initrds = Lists.newArrayList();
            for (String initrd : initrdExecution.getStdOut().split("\n")) {
                initrd = initrd.trim();
                if (initrd.isEmpty()) {
                    continue;
                }
                if (initrd.endsWith(".bak")) {
                    continue;
                }
                initrds.add(initrd);
            }
            if (initrds.size() > 1) {
                throw new IllegalStateException("Multiple initrds found");
            } else if (initrds.size() != 1) {
                throw new IllegalStateException("No initrds found");
            }
            String conf = String.format("default linux\ntimeout 1\n\nlabel linux\nkernel %s\nappend initrd=%s root=UUID=%s ro quiet", kernels.get(0), initrds.get(0), uuid);
            FileUpload.upload(target, new File(rootfsDir, "extlinux.conf"), conf);
            log.info("extlinux.conf = " + conf);
        }
        target.executeCommand(Command.build("extlinux --install  {0}", rootfsDir).setTimeout(TimeSpan.FIVE_MINUTES));
    }
    if (supportCloudConfigDisk) {
        if (useConfigDriveSymlinks) {
            target.rm(new File(rootfsDir, "etc/network/interfaces"));
            target.executeCommand("ln -s /media/config/etc/network/interfaces {0}", new File(rootfsDir, "etc/network/interfaces"));
            target.mkdir(new File(rootfsDir, "root/.ssh"));
            target.executeCommand("ln -s /media/config/root/.ssh/authorized_keys {0}", new File(rootfsDir, "root/.ssh/authorized_keys"));
        } else {
            String initScript = ResourceUtils.get(getClass(), "openstack-config");
            File initScriptFile = new File(rootfsDir, "etc/init.d/openstack-config");
            FileUpload.upload(target, initScriptFile, initScript);
            target.executeCommand("chmod +x {0}", initScriptFile);
            chrootTarget.executeCommand("/usr/sbin/update-rc.d openstack-config defaults");
        }
    }
    {
        // Remove policy file
        File policyFile = new File(rootfsDir, "usr/sbin/policy-rc.d");
        target.rm(policyFile);
    }
    target.executeCommand("sync");
    target.executeCommand("umount {0}", new File(rootfsDir, "proc"));
    if (!buildTar) {
        target.executeCommand("sync");
        target.executeCommand("umount {0}", rootfsDir);
        target.executeCommand("sync");
        target.executeCommand("kpartx -d {0}", imageFile);
        target.executeCommand("sync");
    }
    if (buildTar) {
        Command compress = Command.build("cd {0}; tar jcf {1} .", rootfsDir, imageFile);
        target.executeCommand(compress.setTimeout(TimeSpan.FIFTEEN_MINUTES));
    }
    FilesystemInfo imageInfo = target.getFilesystemInfoFile(imageFile);
    File uploadImageFile;
    if (!buildTar) {
        boolean isQcow2 = imageFormat == ImageFormat.DiskQcow2;
        if (isQcow2) {
            // We create the image as a raw image (making use of sparse files)
            // and then convert it to qcow2. This is a little less efficient, but
            // has a few advantages...
            // 1) We can support different formats
            // 2) The final image is defragmented
            // 3) Mounting a qcow2 image (or other image formats) is tricky vs
            // loopback mount
            uploadImageFile = new File(imageFile.getParentFile(), "image.qcow2");
            command = Command.build("qemu-img convert -f raw -O qcow2 {0} {1}", imageFile, uploadImageFile);
            command.setTimeout(TimeSpan.THIRTY_MINUTES);
            target.executeCommand(command);
        } else {
            uploadImageFile = new File(imageFile.getParentFile(), "image.raw.gz");
            command = Command.build("gzip -c --best {0} > {1}", imageFile, uploadImageFile);
            command.setTimeout(TimeSpan.THIRTY_MINUTES);
            target.executeCommand(command);
        }
    } else {
        uploadImageFile = imageFile;
    }
    String imageId;
    // Upload & tag the image with the recipe ID
    {
        Tags tags = new Tags();
        tags.add(Tag.buildParentTag(recipe.getKey()));
        tags.add(imageFormat.toTag());
        imageId = cloud.getImageStore(targetCloud).uploadImage(target, tags, uploadImageFile, imageInfo.size);
    }
    // Tag the recipe with the image ID
    {
        TagChanges tagChanges = new TagChanges();
        tagChanges.addTags.add(Tag.IMAGE_ID.build(imageId));
        platformLayer.changeTags(image.getKey(), tagChanges);
    }
    // Our pessimism proved unfounded...
    opsContext.setFailure(false);
}
Also used : OperatingSystem(org.platformlayer.service.imagefactory.OperatingSystem) MachineProvider(org.platformlayer.ops.machines.MachineProvider) OpsException(org.platformlayer.ops.OpsException) FilesystemInfo(org.platformlayer.ops.filesystem.FilesystemInfo) ProcessExecutionException(org.platformlayer.ops.process.ProcessExecutionException) CommandEnvironment(org.platformlayer.ops.CommandEnvironment) MachineCreationRequest(org.platformlayer.ops.MachineCreationRequest) TagChanges(org.platformlayer.core.model.TagChanges) Machine(org.platformlayer.ops.Machine) ImageFormat(org.platformlayer.ops.images.ImageFormat) SshKey(org.platformlayer.ops.helpers.SshKey) OpsTarget(org.platformlayer.ops.OpsTarget) ChrootOpsTarget(org.platformlayer.ops.ChrootOpsTarget) DiskImageRecipe(org.platformlayer.images.model.DiskImageRecipe) ChrootOpsTarget(org.platformlayer.ops.ChrootOpsTarget) Command(org.platformlayer.ops.Command) ProcessExecution(org.platformlayer.ops.process.ProcessExecution) HostPolicy(org.platformlayer.core.model.HostPolicy) List(java.util.List) File(java.io.File) Tags(org.platformlayer.core.model.Tags)

Aggregations

TagChanges (org.platformlayer.core.model.TagChanges)20 OpsException (org.platformlayer.ops.OpsException)11 OpsProvider (org.platformlayer.ops.OpsProvider)9 Tag (org.platformlayer.core.model.Tag)7 Tags (org.platformlayer.core.model.Tags)5 Tagger (org.platformlayer.ops.tagger.Tagger)5 EndpointInfo (org.platformlayer.core.model.EndpointInfo)4 ItemBase (org.platformlayer.core.model.ItemBase)4 File (java.io.File)3 IOException (java.io.IOException)3 List (java.util.List)3 AddressModel (org.platformlayer.core.model.AddressModel)3 PlatformLayerKey (org.platformlayer.core.model.PlatformLayerKey)3 DirectInstance (org.platformlayer.service.cloud.direct.model.DirectInstance)3 PublicKey (java.security.PublicKey)2 PlatformLayerClient (org.platformlayer.PlatformLayerClient)2 Command (org.platformlayer.ops.Command)2 Handler (org.platformlayer.ops.Handler)2 Machine (org.platformlayer.ops.Machine)2 NetworkAddressPoolAssignment (org.platformlayer.ops.pool.NetworkAddressPoolAssignment)2