Package org.platformlayer.service.cloud.direct.ops.kvm

Source Code of org.platformlayer.service.cloud.direct.ops.kvm.KvmInstance

package org.platformlayer.service.cloud.direct.ops.kvm;

import java.io.File;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.inject.Inject;

import org.platformlayer.core.model.AddressModel;
import org.platformlayer.core.model.PlatformLayerKey;
import org.platformlayer.core.model.Tag;
import org.platformlayer.core.model.TagChanges;
import org.platformlayer.ops.Command;
import org.platformlayer.ops.Handler;
import org.platformlayer.ops.OpsContext;
import org.platformlayer.ops.OpsException;
import org.platformlayer.ops.OpsProvider;
import org.platformlayer.ops.OpsTarget;
import org.platformlayer.ops.filesystem.ManagedDirectory;
import org.platformlayer.ops.images.ImageFormat;
import org.platformlayer.ops.networks.InterfaceModel;
import org.platformlayer.ops.pool.NetworkAddressPoolAssignment;
import org.platformlayer.ops.pool.SocketAddressPoolAssignment;
import org.platformlayer.ops.process.ProcessExecution;
import org.platformlayer.ops.tagger.Tagger;
import org.platformlayer.ops.templates.TemplateDataSource;
import org.platformlayer.ops.tree.OpsTreeBase;
import org.platformlayer.service.cloud.direct.model.DirectHost;
import org.platformlayer.service.cloud.direct.model.DirectInstance;
import org.platformlayer.service.cloud.direct.ops.CloudInstanceMapper;
import org.platformlayer.service.cloud.direct.ops.DirectCloudUtils;
import org.platformlayer.service.cloud.direct.ops.DownloadImage;
import org.platformlayer.service.cloud.direct.ops.kvm.monitor.KvmConfig.KvmDrive;
import org.platformlayer.service.cloud.direct.ops.kvm.monitor.KvmConfig.KvmNic;

import com.fathomdb.crypto.OpenSshUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Provider;

public class KvmInstance extends OpsTreeBase {
  public PlatformLayerKey owner;

  public File instanceDir;
  public String id;
  public int minimumMemoryMB;
  public PlatformLayerKey recipeId;
  public PublicKey sshPublicKey;

  // public MachineCreationRequest request;

  @Inject
  DirectCloudUtils directCloudHelpers;

  private File getInstanceDir() {
    return instanceDir;
  }

  String getEthernetDeviceName() {
    return "tun_" + id + "_0";
  }

  File getImagePath() {
    return new File(getInstanceDir(), "drive0");
  }

  File getConfigIsoPath() {
    return new File(getInstanceDir(), "config.iso");
  }

  @Handler
  public void handler() {
  }

  @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));
    }
  }

  protected Map<String, String> asMap(Properties properties) {
    Map<String, String> map = Maps.newHashMap();
    for (Object key : properties.keySet()) {
      map.put((String) key, (String) properties.get(key));
    }
    return map;
  }

  private List<KvmNic> buildVnics() {
    List<KvmNic> nics = Lists.newArrayList();

    {
      KvmNic nic = new KvmNic();
      nic.device = getEthernetDeviceName();
      // nic.mac ;
      // Also verify that the guest's running Kernel has CONFIG_PCI_MSI enabled:
      //
      // grep CONFIG_PCI_MSI /boot/config-`uname -r`
      // If both conditions are met, use the vhost-net driver by starting the guest with the following example
      // command line:
      //
      // qemu-kvm [...] -netdev tap,id=guest0,vhost=on,script=no
      // -net nic,model=virtio,netdev=guest0,macaddr=00:16:35:AF:94:4B
      //
      // qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio
      nic.model = "virtio"; // "e1000";
      nic.name = "nic0";
      nics.add(nic);
    }

    return nics;
  }

  private Provider<List<KvmDrive>> buildDrives() {
    return new Provider<List<KvmDrive>>() {
      @Override
      public List<KvmDrive> get() {
        List<KvmDrive> drives = Lists.newArrayList();

        {
          KvmDrive drive = new KvmDrive();
          drive.path = getImagePath().getAbsolutePath();
          drive.id = "0";
          drive.boot = true;
          drive.format = "raw";
          drive.media = "disk";

          OpsTarget target = OpsContext.get().getInstance(OpsTarget.class);
          ProcessExecution fileCommand;
          try {
            fileCommand = target.executeCommand(Command.build("file --brief {0}", getImagePath()));
          } catch (OpsException e) {
            throw new IllegalStateException("Error querying file type", e);
          }
          String fileStdout = fileCommand.getStdOut();
          if (fileStdout.contains("QCOW Image")) {
            drive.format = "qcow2";
          }

          drives.add(drive);
        }
        {
          KvmDrive drive = new KvmDrive();

          drive.path = getConfigIsoPath().getAbsolutePath();
          drive.id = "config";
          drive.boot = false;
          drive.format = "raw";
          drive.media = "cdrom";

          drives.add(drive);
        }

        return drives;
      }
    };

  }
}
TOP

Related Classes of org.platformlayer.service.cloud.direct.ops.kvm.KvmInstance

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.