func (d *Dispatcher) destroyResourcePoolIfEmpty(conf *config.VirtualContainerHostConfigSpec) error { defer trace.End(trace.Begin("")) log.Infof("Removing Resource Pool %q", conf.Name) rpRef := conf.ComputeResources[len(conf.ComputeResources)-1] rp := compute.NewResourcePool(d.ctx, d.session, rpRef) var vms []*vm.VirtualMachine var err error if vms, err = rp.GetChildrenVMs(d.ctx, d.session); err != nil { err = errors.Errorf("Unable to get children vm of resource pool %q: %s", rp.Name(), err) return err } if len(vms) != 0 { err = errors.Errorf("Resource pool is not empty: %q", rp.Name()) return err } if _, err := tasks.WaitForResult(d.ctx, func(ctx context.Context) (tasks.ResultWaiter, error) { return rp.Destroy(ctx) }); err != nil { return err } return nil }
// GetImageVersion will read iso file version from Primary Volume Descriptor, field "Publisher Identifier" func (i *Images) GetImageVersion(img string) (string, error) { defer trace.End(trace.Begin("")) f, err := os.Open(img) if err != nil { return "", errors.Errorf("failed to open iso file %q: %s", img, err) } defer f.Close() // System area goes from sectors 0x00 to 0x0F. Volume descriptors can be // found starting at sector 0x10 _, err = f.Seek(int64(ISOVolumeSector*ISO9660SectorSize)+PublisherOffset, 0) if err != nil { return "", errors.Errorf("failed to locate iso version section in file %q: %s", img, err) } publisherBytes := make([]byte, 128) size, err := f.Read(publisherBytes) if err != nil { return "", errors.Errorf("failed to read iso version in file %q: %s", img, err) } if size == 0 { return "", errors.Errorf("version is not set in iso file %q", img) } versions := strings.Fields(string(publisherBytes[:size])) return versions[len(versions)-1], nil }
func (d *Dispatcher) InspectVCH(vch *vm.VirtualMachine, conf *config.VirtualContainerHostConfigSpec) error { defer trace.End(trace.Begin(conf.Name)) state, err := vch.PowerState(d.ctx) if err != nil { log.Errorf("Failed to get VM power state, service might not be available at this moment.") } if state != types.VirtualMachinePowerStatePoweredOn { err = errors.Errorf("VCH is not powered on, state %s", state) log.Errorf("%s", err) return err } clientIP := conf.ExecutorConfig.Networks["client"].Assigned.IP externalIP := conf.ExecutorConfig.Networks["external"].Assigned.IP if ip.IsUnspecifiedIP(clientIP) { err = errors.Errorf("No client IP address assigned") log.Errorf("%s", err) return err } if ip.IsUnspecifiedIP(externalIP) { err = errors.Errorf("No external IP address assigned") log.Errorf("%s", err) return err } d.HostIP = clientIP.String() log.Debugf("IP address for client interface: %s", d.HostIP) if !conf.HostCertificate.IsNil() { d.VICAdminProto = "https" d.DockerPort = fmt.Sprintf("%d", opts.DefaultTLSHTTPPort) } else { d.VICAdminProto = "http" d.DockerPort = fmt.Sprintf("%d", opts.DefaultHTTPPort) } // try looking up preferred name, irrespective of CAs if cert, err := conf.HostCertificate.X509Certificate(); err == nil { name, _ := viableHostAddress([]net.IP{clientIP}, cert, conf.CertificateAuthorities) if name != "" { log.Debugf("Retrieved proposed name from host certificate: %q", name) log.Debugf("Assigning first name from set: %s", name) if name != d.HostIP { log.Infof("Using address from host certificate over allocated IP: %s", d.HostIP) // reassign d.HostIP = name } } else { log.Warnf("Unable to identify address acceptable to host certificate") } } else { log.Debugf("Failed to load host cert: %s", err) } d.ShowVCH(conf, "", "", "", "") return nil }
// syncContainerCache runs once at startup to populate the container cache func syncContainerCache() error { log.Debugf("Updating container cache") backend := NewContainerBackend() client := backend.containerProxy.Client() reqParams := containers.NewGetContainerListParamsWithContext(ctx).WithAll(swag.Bool(true)) containme, err := client.Containers.GetContainerList(reqParams) if err != nil { return errors.Errorf("Failed to retrieve container list from portlayer: %s", err) } log.Debugf("Found %d containers", len(containme.Payload)) cc := cache.ContainerCache() var errs []string for _, info := range containme.Payload { container := ContainerInfoToVicContainer(*info) cc.AddContainer(container) if err = setPortMapping(info, backend, container); err != nil { errs = append(errs, err.Error()) } } if len(errs) > 0 { return errors.Errorf("Failed to set port mapping: %s", strings.Join(errs, "\n")) } return nil }
func (d *Dispatcher) InspectVCH(vch *vm.VirtualMachine, conf *config.VirtualContainerHostConfigSpec) error { defer trace.End(trace.Begin(conf.Name)) state, err := vch.PowerState(d.ctx) if err != nil { log.Errorf("Failed to get VM power state, service might not be avaialble at this moment.") } if state != types.VirtualMachinePowerStatePoweredOn { err = errors.Errorf("VCH is not powered on, state %s", state) log.Errorf("%s", err) return err } if ip.IsUnspecifiedIP(conf.ExecutorConfig.Networks["client"].Assigned.IP) { err = errors.Errorf("No client IP address assigned") log.Errorf("%s", err) return err } d.HostIP = conf.ExecutorConfig.Networks["client"].Assigned.IP.String() log.Debug("IP address for client interface: %s", d.HostIP) if !conf.HostCertificate.IsNil() { d.VICAdminProto = "https" d.DockerPort = fmt.Sprintf("%d", opts.DefaultTLSHTTPPort) } else { d.VICAdminProto = "http" d.DockerPort = fmt.Sprintf("%d", opts.DefaultHTTPPort) } d.ShowVCH(conf, "", "") return nil }
// saveCertificate saves the certificate and key to files of the form basename-cert.pem and basename-key.pem // cf and kf are the certificate file and key file respectively func saveCertificate(cf, kf string, cert, key *bytes.Buffer) error { defer trace.End(trace.Begin("")) certFile, err := os.OpenFile(cf, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { err = errors.Errorf("Failed to create certificate file %s: %s", cf, err) return err } defer certFile.Close() _, err = certFile.Write(cert.Bytes()) if err != nil { err = errors.Errorf("Failed to write certificate: %s", err) return err } keyFile, err := os.OpenFile(kf, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { err = errors.Errorf("Failed to create key file %s: %s", kf, err) return err } defer keyFile.Close() _, err = keyFile.Write(key.Bytes()) if err != nil { err = errors.Errorf("Failed to write key: %s", err) return err } return nil }
// createCertificate creates a certificate from the supplied template: // template: an x509 template describing the certificate to generate. // parent: either a CA certificate, or template (for self-signed). If nil, will use template. // templateKey: the private key for the certificate supplied as template // parentKey: the private key for the certificate supplied as parent (whether CA or self-signed). If nil will use templateKey // // return PEM encoded certificate and key func createCertificate(template, parent *x509.Certificate, templateKey, parentKey *rsa.PrivateKey) (cert bytes.Buffer, key bytes.Buffer, err error) { defer trace.End(trace.Begin("")) if parent == nil { parent = template } if parentKey == nil { parentKey = templateKey } derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, &templateKey.PublicKey, parentKey) if err != nil { err = errors.Errorf("Failed to generate x509 certificate: %s", err) return cert, key, err } err = pem.Encode(&cert, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) if err != nil { err = errors.Errorf("Failed to encode x509 certificate: %s", err) return cert, key, err } err = pem.Encode(&key, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(templateKey)}) if err != nil { err = errors.Errorf("Failed to encode tls key pairs: %s", err) return cert, key, err } return cert, key, nil }
func (k *Keypair) generate() error { cert, key, err := CreateRawKeyPair() if err != nil { return err } certFile, err := os.Create(k.certFile) if err != nil { err = errors.Errorf("Failed to create key/cert file %s: %s", k.certFile, err) return err } defer certFile.Close() _, err = certFile.Write(cert.Bytes()) if err != nil { err = errors.Errorf("Failed to write certificate: %s", err) return err } keyFile, err := os.Create(k.keyFile) if err != nil { err = errors.Errorf("Failed to create key/cert file %s: %s", k.keyFile, err) return err } defer keyFile.Close() _, err = keyFile.Write(key.Bytes()) if err != nil { err = errors.Errorf("Failed to write certificate: %s", err) return err } k.KeyPEM = key.Bytes() k.CertPEM = cert.Bytes() return nil }
func (d *Dispatcher) CreateVCH(conf *config.VirtualContainerHostConfigSpec, settings *data.InstallerData) error { defer trace.End(trace.Begin(conf.Name)) var err error if err = d.checkExistence(conf, settings); err != nil { return err } if d.isVC && !settings.UseRP { if d.vchVapp, err = d.createVApp(conf, settings); err != nil { detail := fmt.Sprintf("Creating virtual app failed: %s", err) if !d.force { return errors.New(detail) } log.Error(detail) log.Errorf("Deploying vch under parent pool %q, (--force=true)", settings.ResourcePoolPath) d.vchPool = d.session.Pool conf.ComputeResources = append(conf.ComputeResources, d.vchPool.Reference()) } } else { if d.vchPool, err = d.createResourcePool(conf, settings); err != nil { detail := fmt.Sprintf("Creating resource pool failed: %s", err) if !d.force { return errors.New(detail) } log.Error(detail) log.Errorf("Deploying vch under parent pool %q, (--force=true)", settings.ResourcePoolPath) d.vchPool = d.session.Pool conf.ComputeResources = append(conf.ComputeResources, d.vchPool.Reference()) } } if err = d.createBridgeNetwork(conf); err != nil { return err } if err = d.createVolumeStores(conf); err != nil { return errors.Errorf("Exiting because we could not create volume stores due to error: %s", err) } if err = d.createAppliance(conf, settings); err != nil { return errors.Errorf("Creating the appliance failed with %s. Exiting...", err) } if err = d.uploadImages(settings.ImageFiles); err != nil { return errors.Errorf("Uploading images failed with %s. Exiting...", err) } if d.session.IsVC() { if err = d.RegisterExtension(conf, settings.Extension); err != nil { return errors.Errorf("Error registering VCH vSphere extension: %s", err) } } return d.startAppliance(conf) }
func (d *Dispatcher) deleteVM(vm *vm.VirtualMachine, force bool) error { defer trace.End(trace.Begin(fmt.Sprintf("vm %q, force %t", vm.String(), force))) var err error power, err := vm.PowerState(d.ctx) if err != nil || power != types.VirtualMachinePowerStatePoweredOff { if err != nil { log.Warnf("Failed to get vm power status %q: %s", vm.Reference(), err) } if !force { if err != nil { return err } name := d.getName(vm) if name != "" { err = errors.Errorf("VM %q is powered on", name) } else { err = errors.Errorf("VM %q is powered on", vm.Reference()) } return err } if _, err = vm.WaitForResult(d.ctx, func(ctx context.Context) (tasks.Task, error) { return vm.PowerOff(ctx) }); err != nil { log.Debugf("Failed to power off existing appliance for %s, try to remove anyway", err) } } // get the actual folder name before we delete it folder, err := vm.FolderName(d.ctx) if err != nil { // failed to get folder name, might not be able to remove files for this VM name := d.getName(vm) if name == "" { log.Errorf("Unable to automatically remove all files in datastore for VM %q", vm.Reference()) } else { // try to use the vm name in place of folder log.Infof("Delete will attempt to remove datastore files for VM %q", name) folder = name } } _, err = vm.WaitForResult(d.ctx, func(ctx context.Context) (tasks.Task, error) { return vm.DeleteExceptDisks(ctx) }) if err != nil { err = errors.Errorf("Failed to destroy VM %q: %s", vm.Reference(), err) err2 := vm.Unregister(d.ctx) if err2 != nil { return errors.Errorf("%s then failed to unregister VM: %s", err, err2) } log.Infof("Unregistered VM to cleanup after failed destroy: %q", vm.Reference()) } if _, err = d.deleteDatastoreFiles(d.session.Datastore, folder, true); err != nil { log.Warnf("Failed to remove datastore files for VM path %q: %s", folder, err) } return nil }
func (d *Dispatcher) DeleteVCHInstances(vmm *vm.VirtualMachine, conf *config.VirtualContainerHostConfigSpec) error { defer trace.End(trace.Begin("")) log.Infof("Removing VMs") var errs []string var err error var children []*vm.VirtualMachine rpRef := conf.ComputeResources[len(conf.ComputeResources)-1] ref, err := d.session.Finder.ObjectReference(d.ctx, rpRef) if err != nil { err = errors.Errorf("Failed to get VCH resource pool %q: %s", rpRef, err) return err } switch ref.(type) { case *object.VirtualApp: case *object.ResourcePool: // ok default: log.Errorf("Failed to find virtual app or resource pool %q: %s", rpRef, err) return err } rp := compute.NewResourcePool(d.ctx, d.session, ref.Reference()) if children, err = rp.GetChildrenVMs(d.ctx, d.session); err != nil { return err } ds, err := d.session.Finder.Datastore(d.ctx, conf.ImageStores[0].Host) if err != nil { err = errors.Errorf("Failed to find image datastore %q", conf.ImageStores[0].Host) return err } d.session.Datastore = ds for _, child := range children { name, err := child.Name(d.ctx) if err != nil { errs = append(errs, err.Error()) continue } //Leave VCH appliance there until everything else is removed, cause it has VCH configuration. Then user could retry delete in case of any failure. if name == conf.Name { continue } if err = d.deleteVM(child, d.force); err != nil { errs = append(errs, err.Error()) } } if len(errs) > 0 { log.Debugf("Error deleting container VMs %s", errs) return errors.New(strings.Join(errs, "\n")) } return nil }
func (d *Dispatcher) createBridgeNetwork(conf *config.VirtualContainerHostConfigSpec) error { defer trace.End(trace.Begin("")) // if the bridge network is already extant there's nothing to do bnet := conf.ExecutorConfig.Networks[conf.BridgeNetwork] if bnet != nil && bnet.ID != "" { return nil } // network didn't exist during validation given we don't have a moref, so create it if d.session.Client.IsVC() { // double check return errors.New("bridge network must already exist for vCenter environments") } // in this case the name to use is held in container network ID name := bnet.Network.ID log.Infof("Creating VirtualSwitch") hostNetSystem, err := d.session.Host.ConfigManager().NetworkSystem(d.ctx) if err != nil { err = errors.Errorf("Failed to retrieve host network system: %s", err) return err } if err = hostNetSystem.AddVirtualSwitch(d.ctx, name, &types.HostVirtualSwitchSpec{ NumPorts: 1024, }); err != nil { err = errors.Errorf("Failed to add virtual switch (%q): %s", name, err) return err } log.Infof("Creating Portgroup") if err = hostNetSystem.AddPortGroup(d.ctx, types.HostPortGroupSpec{ Name: name, VlanId: 1, // TODO: expose this for finer grained grouping within the switch VswitchName: name, Policy: types.HostNetworkPolicy{}, }); err != nil { err = errors.Errorf("Failed to add port group (%q): %s", name, err) return err } net, err := d.session.Finder.Network(d.ctx, name) if err != nil { _, ok := err.(*find.NotFoundError) if !ok { err = errors.Errorf("Failed to query virtual switch (%q): %s", name, err) return err } } // assign the moref to the bridge network config on the appliance bnet.ID = net.Reference().String() bnet.Network.ID = net.Reference().String() conf.CreateBridgeNetwork = true return nil }
// Connect establishes the connection for the session but nothing more func (s *Session) Connect(ctx context.Context) (*Session, error) { soapURL, err := soap.ParseURL(s.Service) if soapURL == nil || err != nil { return nil, errors.Errorf("SDK URL (%s) could not be parsed: %s", s.Service, err) } // update the service URL with the resolved soapURL s.Service = soapURL.String() // we can't set a keep alive if we log in directly with client creation user := soapURL.User soapURL.User = nil // 1st connect without any userinfo to get the API type s.Client, err = govmomi.NewClient(ctx, soapURL, s.Insecure) if err != nil { return nil, errors.Errorf("Failed to connect to %s: %s", soapURL.String(), err) } if s.HasCertificate() && s.Client.IsVC() { // load the certificates cert, err2 := tls.X509KeyPair([]byte(s.ExtensionCert), []byte(s.ExtensionKey)) if err2 != nil { return nil, errors.Errorf("Unable to load X509 key pair(%s,%s): %s", s.ExtensionCert, s.ExtensionKey, err2) } // create the new client s.Client, err = govmomi.NewClientWithCertificate(ctx, soapURL, s.Insecure, cert) if err != nil { return nil, errors.Errorf("Failed to connect to %s: %s", soapURL.String(), err) } } if s.Keepalive != 0 { // now that we've verified everything, enable keepalive s.RoundTripper = session.KeepAlive(s.Client.RoundTripper, s.Keepalive) } // and now that the keepalive is registered we can log in to trigger it if !s.IsVC() || !s.HasCertificate() { log.Debugf("Trying to log in with username/password in lieu of cert") err = s.Client.Login(ctx, user) } else { log.Debugf("Logging into extension %s", s.ExtensionName) err = s.LoginExtensionByCertificate(ctx, s.ExtensionName, "") } if err != nil { return nil, errors.Errorf("Failed to log in to %s: %s", soapURL.String(), err) } s.Finder = find.NewFinder(s.Vim25(), true) // log high-level environement information s.logEnvironmentInfo() return s, nil }
func (d *Dispatcher) NewVCHFromComputePath(computePath string, name string, v *validate.Validator) (*vm.VirtualMachine, error) { defer trace.End(trace.Begin(fmt.Sprintf("path %q, name %q", computePath, name))) var err error parent, err := v.ResourcePoolHelper(d.ctx, computePath) if err != nil { return nil, err } d.vchPoolPath = path.Join(parent.InventoryPath, name) var vchPool *object.ResourcePool if d.isVC { vapp, err := d.findVirtualApp(d.vchPoolPath) if err != nil { log.Errorf("Failed to get VCH virtual app %q: %s", d.vchPoolPath, err) return nil, err } if vapp != nil { vchPool = vapp.ResourcePool } } if vchPool == nil { vchPool, err = d.session.Finder.ResourcePool(d.ctx, d.vchPoolPath) if err != nil { log.Errorf("Failed to get VCH resource pool %q: %s", d.vchPoolPath, err) return nil, err } } rp := compute.NewResourcePool(d.ctx, d.session, vchPool.Reference()) var vmm *vm.VirtualMachine if vmm, err = rp.GetChildVM(d.ctx, d.session, name); err != nil { log.Errorf("Failed to get VCH VM: %s", err) return nil, err } if vmm == nil { err = errors.Errorf("Didn't find VM %q in resource pool %q", name, rp.Name()) log.Error(err) return nil, err } vmm.InventoryPath = path.Join(d.vchPoolPath, name) // check if it's VCH var ok bool if ok, err = d.isVCH(vmm); err != nil { log.Error(err) return nil, err } if !ok { err = errors.Errorf("Not a VCH") log.Error(err) return nil, err } return vmm, nil }
func (d *Dispatcher) addNetworkDevices(conf *metadata.VirtualContainerHostConfigSpec, cspec *spec.VirtualMachineConfigSpec, devices object.VirtualDeviceList) (object.VirtualDeviceList, error) { defer trace.End(trace.Begin("")) // network name:alias, to avoid create multiple devices for same network slots := make(map[int32]bool) nets := make(map[string]*metadata.NetworkEndpoint) for name, endpoint := range conf.ExecutorConfig.Networks { if pnic, ok := nets[endpoint.Network.Common.ID]; ok { // there's already a NIC on this network endpoint.Common.ID = pnic.Common.ID log.Infof("Network role %s is sharing NIC with %s", name, pnic.Network.Common.Name) continue } moref := new(types.ManagedObjectReference) if ok := moref.FromString(endpoint.Network.ID); !ok { return nil, fmt.Errorf("serialized managed object reference in unexpected format: %s", endpoint.Network.ID) } obj, err := d.session.Finder.ObjectReference(d.ctx, *moref) if err != nil { return nil, fmt.Errorf("unable to reacquire reference for network %s from serialized form: %s", endpoint.Network.Name, endpoint.Network.ID) } network, ok := obj.(object.NetworkReference) if !ok { return nil, fmt.Errorf("reacquired reference for network %s, from serialized form %s, was not a network: %T", endpoint.Network.Name, endpoint.Network.ID, obj) } backing, err := network.EthernetCardBackingInfo(d.ctx) if err != nil { err = errors.Errorf("Failed to get network backing info for %s: %s", network, err) return nil, err } nic, err := devices.CreateEthernetCard("vmxnet3", backing) if err != nil { err = errors.Errorf("Failed to create Ethernet Card spec for %s", err) return nil, err } slot := cspec.AssignSlotNumber(nic, slots) if slot == spec.NilSlot { err = errors.Errorf("Failed to assign stable PCI slot for %s network card", name) } endpoint.Common.ID = strconv.Itoa(int(slot)) slots[slot] = true log.Debugf("Setting %s to slot %d", name, slot) devices = append(devices, nic) nets[endpoint.Network.Common.ID] = endpoint } return devices, nil }
func (d *Dispatcher) deleteVM(vm *vm.VirtualMachine, force bool) error { defer trace.End(trace.Begin("")) var err error power, err := vm.PowerState(d.ctx) if err != nil || power != types.VirtualMachinePowerStatePoweredOff { if err != nil { log.Warnf("Failed to get vm power status %s: %s", vm.Reference(), err) } if !force { if err != nil { return err } name, err := vm.Name(d.ctx) if err != nil { log.Errorf("VM name is not found, %s", err) } if name != "" { err = errors.Errorf("VM %s is powered on", name) } else { err = errors.Errorf("VM %s is powered on", vm.Reference()) } return err } if _, err = tasks.WaitForResult(d.ctx, func(ctx context.Context) (tasks.ResultWaiter, error) { return vm.PowerOff(ctx) }); err != nil { log.Debugf("Failed to power off existing appliance for %s, try to remove anyway", err) } } // get the actual folder name before we delete it folder, err := vm.FolderName(d.ctx) if err != nil { log.Warnf("Failed to get actual folder name for VM. Will not attempt to delete additional data files in VM directory: %s", err) } _, err = tasks.WaitForResult(d.ctx, func(ctx context.Context) (tasks.ResultWaiter, error) { return vm.Destroy(ctx) }) if err != nil { err = errors.Errorf("Failed to destroy vm %s: %s", vm.Reference(), err) return err } if _, err = d.deleteDatastoreFiles(d.session.Datastore, folder, true); err != nil { log.Warnf("VM path %s is not removed, %s", folder, err) } return nil }
// CreateRawKeyPair generates a default certificate / key and returns them as bytes buffers // If you wish to save them to files as a side effect, use GetCertificate() instead func CreateRawKeyPair() (cert bytes.Buffer, key bytes.Buffer, err error) { org := "VMware" priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return cert, key, err } notBefore := time.Now() notAfter := notBefore.Add(365 * 24 * time.Hour) // 1 year serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { err = errors.Errorf("Failed to generate random number: %s", err) return cert, key, err } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{org}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, BasicConstraintsValid: true, } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { err = errors.Errorf("Failed to generate x509 certificate: %s", err) return cert, key, err } err = pem.Encode(&cert, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) if err != nil { err = errors.Errorf("Failed to encode x509 certificate: %s", err) return cert, key, err } err = pem.Encode(&key, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) if err != nil { err = errors.Errorf("Failed to encode tls key pairs: %s", err) return cert, key, err } return cert, key, nil }
func (c *Create) loadCertificates() ([]byte, *certificate.KeyPair, error) { defer trace.End(trace.Begin("")) c.envFile = fmt.Sprintf("%s.env", c.DisplayName) // reads each of the files specified, assuming that they are PEM encoded certs, // and constructs a byte array suitable for passing to CertPool.AppendCertsFromPEM var certs []byte for _, f := range c.clientCAs { log.Infof("Loading CA from %s", f) b, err := ioutil.ReadFile(f) if err != nil { err = errors.Errorf("Failed to load authority from file %s: %s", f, err) return nil, nil, err } certs = append(certs, b...) } var keypair *certificate.KeyPair if c.cert != "" && c.key != "" { log.Infof("Loading certificate/key pair - private key in %s", c.key) keypair = certificate.NewKeyPair(c.cert, c.key, nil, nil) if err := keypair.LoadCertificate(); err != nil { log.Errorf("Failed to load certificate: %s", err) return certs, nil, err } } return certs, keypair, nil }
func (d *Dispatcher) findApplianceByID(conf *metadata.VirtualContainerHostConfigSpec) (*vm.VirtualMachine, error) { defer trace.End(trace.Begin("")) var err error var vmm *vm.VirtualMachine moref := new(types.ManagedObjectReference) if ok := moref.FromString(conf.ID); !ok { message := "Failed to get appliance VM mob reference" log.Errorf(message) return nil, errors.New(message) } ref, err := d.session.Finder.ObjectReference(d.ctx, *moref) if err != nil { if _, ok := err.(*find.NotFoundError); !ok { err = errors.Errorf("Failed to query appliance (%s): %s", moref, err) return nil, err } log.Debugf("Appliance is not found") return nil, nil } ovm, ok := ref.(*object.VirtualMachine) if !ok { log.Errorf("Failed to find VM %s, %s", moref, err) return nil, err } vmm = vm.NewVirtualMachine(d.ctx, d.session, ovm.Reference()) return vmm, nil }
func (d *Dispatcher) deleteDatastoreFiles(ds *object.Datastore, path string, force bool) (bool, error) { defer trace.End(trace.Begin(fmt.Sprintf("path %q, force %t", path, force))) // refuse to delete everything on the datstore, ignore force if path == "" { dsn, _ := ds.ObjectName(d.ctx) msg := fmt.Sprintf("refusing to remove datastore files for path \"\" on datastore %q", dsn) return false, errors.New(msg) } var empty bool dsPath := ds.Path(path) res, err := d.lsFolder(ds, dsPath) if err != nil { if !types.IsFileNotFound(err) { err = errors.Errorf("Failed to browse folder %q: %s", dsPath, err) return empty, err } log.Debugf("Folder %q is not found", dsPath) empty = true return empty, nil } if len(res.File) > 0 && !force { log.Debugf("Folder %q is not empty, leave it there", dsPath) return empty, nil } m := object.NewFileManager(ds.Client()) if err = d.deleteFilesIteratively(m, ds, dsPath); err != nil { return empty, err } return true, nil }
func template(org []string) *x509.Certificate { now := time.Now().UTC() // help address issues with clock drift notBefore := now.AddDate(0, 0, -1) notAfter := now.AddDate(1, 0, 0) // 1 year serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { err = errors.Errorf("Failed to generate random number: %s", err) return nil } // ensure that org is set to something if len(org) == 0 { org = []string{"default"} } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: org, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement, BasicConstraintsValid: true, } return &template }
func waitForPath(op trace.Operation, path string) error { defer trace.End(trace.Begin(path)) timeout := time.Duration(pathTimeout) op, _ = trace.WithTimeout(&op, timeout, path) done := make(chan struct{}) go func() { t := time.NewTicker(200 * time.Microsecond) defer t.Stop() for range t.C { if _, err := os.Stat(path); err == nil { close(done) break } // We've timed out. if op.Err() != nil { break } } }() log.Debugf("Waiting for attached disk to appear in /dev/disk/by-path, or timeout") select { case <-done: log.Infof("Attached disk present at %s", path) case <-op.Done(): if op.Err() != nil { return errors.Errorf("timeout waiting for layer to present as %s", path) } } return nil }
func (d *Dispatcher) searchVCHsPerDC(dc *object.Datacenter) ([]*vm.VirtualMachine, error) { defer trace.End(trace.Begin(dc.InventoryPath)) var err error var pools []*object.ResourcePool d.session.Datacenter = dc d.session.Finder.SetDatacenter(dc) var vchs []*vm.VirtualMachine if pools, err = d.session.Finder.ResourcePoolList(d.ctx, "*"); err != nil { if _, ok := err.(*find.NotFoundError); ok { return vchs, nil } err = errors.Errorf("Failed to search resource pools for datacenter %q: %s", dc.InventoryPath, err) return nil, err } for _, pool := range pools { chidren, err := d.searchVCHsPerRP(pool) if err != nil { return nil, err } vchs = append(vchs, chidren...) } return vchs, nil }
// Wait wraps govmomi operations and wait the operation to complete // Sample usage: // info, err := Wait(ctx, func(ctx) (*TaskInfo, error) { // return vm.Reconfigure(ctx, config) // }) func Wait(ctx context.Context, f func(context.Context) (Waiter, error)) error { task, err := f(ctx) if err != nil { cerr := errors.Errorf("Failed to invoke operation: %s", errors.ErrorStack(err)) log.Errorf(cerr.Error()) return cerr } err = task.Wait(ctx) if err != nil { cerr := errors.Errorf("Operation failed: %s", errors.ErrorStack(err)) log.Errorf(cerr.Error()) return cerr } return nil }
func waitForPath(ctx context.Context, path string) error { defer trace.End(trace.Begin(path)) timeout := time.Duration(pathTimeout) ctx, _ = context.WithTimeout(ctx, timeout) done := make(chan struct{}) go func() { for { if _, err := os.Stat(path); err == nil { close(done) break } // We've timed out. if ctx.Err() != nil { break } time.Sleep(200 * time.Microsecond) } }() log.Debugf("Waiting for attached disk to appear in /dev/disk/by-path, or timeout") select { case <-done: log.Infof("Attached disk present at %s", path) case <-ctx.Done(): if ctx.Err() != nil { return errors.Errorf("timeout waiting for layer to present as %s", path) } } return nil }
func (d *Dispatcher) RegisterExtension(conf *config.VirtualContainerHostConfigSpec, extension types.Extension) error { defer trace.End(trace.Begin(conf.ExtensionName)) log.Infoln("Registering VCH as a vSphere extension") // vSphere confusingly calls the 'name' of the extension a 'key' // This variable is named IdKey as to not confuse it with its private key if conf.ExtensionCert == "" { return errors.Errorf("Extension certificate does not exist") } extensionManager := object.NewExtensionManager(d.session.Vim25()) extension.LastHeartbeatTime = time.Now().UTC() if err := extensionManager.Register(d.ctx, extension); err != nil { log.Errorf("Could not register the vSphere extension due to err: %s", err) return err } if err := extensionManager.SetCertificate(d.ctx, conf.ExtensionName, conf.ExtensionCert); err != nil { log.Errorf("Could not set the certificate on the vSphere extension due to error: %s", err) return err } return nil }
func (i *Images) checkImageVersion(img string, force bool) (string, error) { defer trace.End(trace.Begin("")) ver, err := i.GetImageVersion(img) if err != nil { return "", err } sv := i.getNoCommitHashVersion(ver) if sv == "" { log.Debugf("Version is not set in %q", img) ver = "" } installerSV := i.getNoCommitHashVersion(version.GetBuild().ShortVersion()) // here compare version without last commit hash, to make developer life easier if !strings.EqualFold(installerSV, sv) { message := fmt.Sprintf("iso file %q version %q inconsistent with installer version %q", img, strings.ToLower(ver), version.GetBuild().ShortVersion()) if !force { return "", errors.Errorf("%s. Specify --force to force create. ", message) } log.Warn(message) } return ver, nil }
func (d *Dispatcher) checkExistence(conf *config.VirtualContainerHostConfigSpec, settings *data.InstallerData) error { defer trace.End(trace.Begin("")) var err error d.vchPoolPath = path.Join(settings.ResourcePoolPath, conf.Name) var orp *object.ResourcePool var vapp *object.VirtualApp if d.isVC { vapp, err = d.findVirtualApp(d.vchPoolPath) if err != nil { return err } if vapp != nil { orp = vapp.ResourcePool } } if orp == nil { if orp, err = d.findResourcePool(d.vchPoolPath); err != nil { return err } } if orp == nil { return nil } rp := compute.NewResourcePool(d.ctx, d.session, orp.Reference()) vm, err := rp.GetChildVM(d.ctx, d.session, conf.Name) if err != nil { return err } if vm == nil { if vapp != nil { err = errors.Errorf("virtual app %q is found, but is not VCH, please choose different name", d.vchPoolPath) log.Error(err) return err } return nil } log.Debugf("Appliance is found") if ok, verr := d.isVCH(vm); !ok { verr = errors.Errorf("VM %q is found, but is not VCH appliance, please choose different name", conf.Name) return verr } err = errors.Errorf("Appliance %q exists, to install with same name, please delete it first.", conf.Name) return err }
func loadCertificate(cf, kf string) (*x509.Certificate, *rsa.PrivateKey, error) { defer trace.End(trace.Begin("")) cb, err := ioutil.ReadFile(cf) if err != nil { err = errors.Errorf("Failed to read certificate file %s: %s", cf, err) return nil, nil, err } kb, err := ioutil.ReadFile(kf) if err != nil { err = errors.Errorf("Failed to read key file %s: %s", kf, err) return nil, nil, err } return ParseCertificate(cb, kb) }
func (d *Dispatcher) UnregisterExtension(name string) error { defer trace.End(trace.Begin(name)) extensionManager := object.NewExtensionManager(d.session.Vim25()) if err := extensionManager.Unregister(d.ctx, name); err != nil { return errors.Errorf("Failed to remove extension w/ name %q due to error: %s", name, err) } return nil }