コード例 #1
0
ファイル: resource_pool.go プロジェクト: kjplatz/vic
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
}
コード例 #2
0
ファイル: images.go プロジェクト: vmware/vic
// 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
}
コード例 #3
0
ファイル: inspect.go プロジェクト: vmware/vic
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
}
コード例 #4
0
ファイル: backends.go プロジェクト: vmware/vic
// 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
}
コード例 #5
0
ファイル: inspect.go プロジェクト: kjplatz/vic
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
}
コード例 #6
0
ファイル: certificate.go プロジェクト: vmware/vic
// 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
}
コード例 #7
0
ファイル: certificate.go プロジェクト: vmware/vic
// 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
}
コード例 #8
0
ファイル: certificate.go プロジェクト: jak-atx/vic
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
}
コード例 #9
0
ファイル: create.go プロジェクト: vmware/vic
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)
}
コード例 #10
0
ファイル: appliance.go プロジェクト: vmware/vic
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
}
コード例 #11
0
ファイル: delete.go プロジェクト: kjplatz/vic
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
}
コード例 #12
0
ファイル: network.go プロジェクト: kjplatz/vic
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
}
コード例 #13
0
ファイル: session.go プロジェクト: jak-atx/vic
// 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
}
コード例 #14
0
ファイル: finder.go プロジェクト: vmware/vic
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
}
コード例 #15
0
ファイル: appliance.go プロジェクト: jak-atx/vic
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
}
コード例 #16
0
ファイル: appliance.go プロジェクト: jak-atx/vic
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
}
コード例 #17
0
ファイル: certificate.go プロジェクト: jak-atx/vic
// 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
}
コード例 #18
0
ファイル: create.go プロジェクト: vmware/vic
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
}
コード例 #19
0
ファイル: appliance.go プロジェクト: jak-atx/vic
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
}
コード例 #20
0
ファイル: store_files.go プロジェクト: vmware/vic
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
}
コード例 #21
0
ファイル: certificate.go プロジェクト: vmware/vic
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
}
コード例 #22
0
ファイル: util.go プロジェクト: vmware/vic
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
}
コード例 #23
0
ファイル: finder.go プロジェクト: vmware/vic
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
}
コード例 #24
0
ファイル: waiter.go プロジェクト: jak-atx/vic
// 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
}
コード例 #25
0
ファイル: util.go プロジェクト: jak-atx/vic
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
}
コード例 #26
0
ファイル: create.go プロジェクト: vmware/vic
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
}
コード例 #27
0
ファイル: images.go プロジェクト: vmware/vic
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
}
コード例 #28
0
ファイル: appliance.go プロジェクト: kjplatz/vic
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
}
コード例 #29
0
ファイル: certificate.go プロジェクト: vmware/vic
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)
}
コード例 #30
0
ファイル: delete.go プロジェクト: kjplatz/vic
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
}