コード例 #1
0
ファイル: vm_test.go プロジェクト: kjplatz/vic
func TestDeleteExceptDisk(t *testing.T) {
	s := os.Getenv("DRONE")
	if s != "" {
		t.Skip("Skipping: test must be run in a VM")
	}

	ctx := context.Background()

	session := test.Session(ctx, t)
	defer session.Logout(ctx)

	host := test.PickRandomHost(ctx, session, t)

	uuid, err := sys.UUID()
	if err != nil {
		t.Fatalf("unable to get UUID for guest - used for VM name: %s", err)
	}
	name := fmt.Sprintf("%s-%d", uuid, rand.Intn(math.MaxInt32))

	moref, err := CreateVM(ctx, session, host, name)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}
	// Wrap the result with our version of VirtualMachine
	vm := NewVirtualMachine(ctx, session, *moref)

	folder, err := vm.FolderName(ctx)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}

	// generate the disk name
	diskName := fmt.Sprintf("%s/%s.vmdk", folder, folder)

	// Delete the VM but not it's disk
	_, err = tasks.WaitForResult(ctx, func(ctx context.Context) (tasks.ResultWaiter, error) {
		return vm.DeleteExceptDisks(ctx)
	})
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}

	// check that the disk still exists
	session.Datastore.Stat(ctx, diskName)
	if err != nil {
		t.Fatalf("Disk does not exist")
	}

	// clean up
	dm := object.NewVirtualDiskManager(session.Client.Client)

	task, err := dm.DeleteVirtualDisk(context.TODO(), diskName, nil)
	if err != nil {
		t.Fatalf("Unable to locate orphan vmdk: %s", err)
	}

	if err = task.Wait(context.TODO()); err != nil {
		t.Fatalf("Unable to remove orphan vmdk: %s", err)
	}
}
コード例 #2
0
ファイル: vm_test.go プロジェクト: kjplatz/vic
func TestVM(t *testing.T) {

	s := os.Getenv("DRONE")
	if s != "" {
		t.Skip("Skipping: test must be run in a VM")
	}

	ctx := context.Background()

	session := test.Session(ctx, t)
	defer session.Logout(ctx)

	host := test.PickRandomHost(ctx, session, t)

	uuid, err := sys.UUID()
	if err != nil {
		t.Fatalf("unable to get UUID for guest - used for VM name: %s", err)
		return
	}
	name := fmt.Sprintf("%s-%d", uuid, rand.Intn(math.MaxInt32))

	moref, err := CreateVM(ctx, session, host, name)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}
	// Wrap the result with our version of VirtualMachine
	vm := NewVirtualMachine(ctx, session, *moref)

	// Check the state
	state, err := vm.PowerState(ctx)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}

	assert.Equal(t, types.VirtualMachinePowerStatePoweredOff, state)

	// Check VM name
	rname, err := vm.Name(ctx)
	if err != nil {
		t.Errorf("Failed to load VM name: %s", err)
	}
	assert.Equal(t, name, rname)

	// Get VM UUID
	ruuid, err := vm.UUID(ctx)
	if err != nil {
		t.Errorf("Failed to load VM UUID: %s", err)
	}
	t.Logf("Got UUID: %s", ruuid)

	// Destroy the vm
	_, err = tasks.WaitForResult(ctx, func(ctx context.Context) (tasks.ResultWaiter, error) {
		return vm.Destroy(ctx)
	})
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}
}
コード例 #3
0
ファイル: system.go プロジェクト: vmware/vic
func New() System {
	id, _ := sys.UUID()
	return System{
		Hosts:      etcconf.NewHosts(""),      // default hosts files, e.g. /etc/hosts on linux
		ResolvConf: etcconf.NewResolvConf(""), // default resolv.conf file, e.g. /etc/resolv.conf on linux
		Syscall:    &syscallImpl{},            // the syscall interface
		Root:       "/",                       // the system root path
		UUID:       id,
	}
}
コード例 #4
0
ファイル: container.go プロジェクト: vmware/vic
func instanceUUID(id string) (string, error) {
	// generate VM instance uuid, which will be used to query back VM
	u, err := sys.UUID()
	if err != nil {
		return "", err
	}
	namespace, err := uuid.Parse(u)
	if err != nil {
		return "", errors.Errorf("unable to parse VCH uuid: %s", err)
	}
	return uuid.NewSHA1(namespace, []byte(id)).String(), nil
}
コード例 #5
0
ファイル: id.go プロジェクト: kjplatz/vic
func getMachineID() ([]byte, error) {
	id, err := sys.UUID()
	if err != nil {
		return nil, err
	}

	uid, err := uuid.Parse(id)
	if err != nil {
		return nil, err
	}

	return uid.MarshalBinary()
}
コード例 #6
0
ファイル: image_cache.go プロジェクト: kjplatz/vic
// Update runs only once at startup to hydrate the image cache
func (ic *ICache) Update(client *client.PortLayer) error {
	log.Debugf("Updating image cache...")

	host, err := sys.UUID()
	if host == "" {
		host, err = os.Hostname()
	}
	if err != nil {
		return fmt.Errorf("Unexpected error getting hostname: %s", err)
	}

	// attempt to create the image store if it doesn't exist
	store := &models.ImageStore{Name: host}
	_, err = client.Storage.CreateImageStore(
		storage.NewCreateImageStoreParamsWithContext(ctx).WithBody(store),
	)

	if err != nil {
		if _, ok := err.(*storage.CreateImageStoreConflict); ok {
			log.Debugf("Store already exists")
		} else {
			log.Debugf("Creating a store failed: %#v", err)
			return err
		}
	}

	params := storage.NewListImagesParamsWithContext(ctx).WithStoreName(host)

	layers, err := client.Storage.ListImages(params)
	if err != nil {
		return fmt.Errorf("Failed to retrieve image list from portlayer: %s", err)
	}

	for _, layer := range layers.Payload {
		imageConfig := &metadata.ImageConfig{}
		if err := json.Unmarshal([]byte(layer.Metadata["metaData"]), imageConfig); err != nil {
			derr.NewErrorWithStatusCode(fmt.Errorf("Failed to unmarshal image config: %s", err),
				http.StatusInternalServerError)
		}

		if imageConfig.ImageID != "" {
			ic.AddImage(imageConfig)
		}
	}

	return nil
}
コード例 #7
0
ファイル: linux.go プロジェクト: kjplatz/vic
// GetSelf gets VirtualMachine reference for the VM this process is running on
func GetSelf(ctx context.Context, s *session.Session) (*object.VirtualMachine, error) {
	u, err := sys.UUID()
	if err != nil {
		return nil, err
	}

	search := object.NewSearchIndex(s.Vim25())
	ref, err := search.FindByUuid(ctx, s.Datacenter, u, true, nil)
	if err != nil {
		return nil, err
	}

	if ref == nil {
		return nil, fmt.Errorf("can't find the hosting vm")
	}

	vm := object.NewVirtualMachine(s.Client.Client, ref.Reference())
	return vm, nil
}
コード例 #8
0
ファイル: container_proxy.go プロジェクト: kjplatz/vic
// CreateContainerHandle creates a new VIC container by calling the portlayer
//
// returns:
// 	(containerID, containerHandle, error)
func (c *ContainerProxy) CreateContainerHandle(imageID string, config types.ContainerCreateConfig) (string, string, error) {
	defer trace.End(trace.Begin(imageID))

	if c.client == nil {
		return "", "",
			derr.NewErrorWithStatusCode(fmt.Errorf("ContainerProxy.CreateContainerHandle failed to create a portlayer client"),
				http.StatusInternalServerError)
	}

	if imageID == "" {
		return "", "",
			derr.NewRequestNotFoundError(fmt.Errorf("No image specified"))
	}

	// Call the Exec port layer to create the container
	host, err := sys.UUID()
	if err != nil {
		return "", "",
			derr.NewErrorWithStatusCode(fmt.Errorf("ContainerProxy.CreateContainerHandle got unexpected error getting VCH UUID"),
				http.StatusInternalServerError)
	}

	plCreateParams := dockerContainerCreateParamsToPortlayer(config, imageID, host)
	createResults, err := c.client.Containers.Create(plCreateParams)
	if err != nil {
		if _, ok := err.(*containers.CreateNotFound); ok {
			cerr := fmt.Errorf("No such image: %s", imageID)
			log.Errorf("%s (%s)", cerr, err)
			return "", "", derr.NewRequestNotFoundError(cerr)
		}

		// If we get here, most likely something went wrong with the port layer API server
		return "", "",
			derr.NewErrorWithStatusCode(err, http.StatusInternalServerError)
	}

	id := createResults.Payload.ID
	h := createResults.Payload.Handle

	return id, h, nil
}
コード例 #9
0
ファイル: vm_test.go プロジェクト: vmware/vic
func TestVMFailureWithTimeout(t *testing.T) {
	ctx := context.Background()

	session := test.Session(ctx, t)
	defer session.Logout(ctx)

	host := test.PickRandomHost(ctx, session, t)

	ctx, cancel := context.WithTimeout(ctx, 1*time.Microsecond)
	defer cancel()

	uuid, err := sys.UUID()
	if err != nil {
		t.Fatalf("unable to get UUID for guest - used for VM name: %s", err)
		return
	}
	name := fmt.Sprintf("%s-%d", uuid, rand.Intn(math.MaxInt32))

	_, err = CreateVM(ctx, session, host, name)
	if err != nil && err != context.DeadlineExceeded {
		t.Fatalf("ERROR: %s", err)
	}
}
コード例 #10
0
ファイル: backends.go プロジェクト: vmware/vic
func createImageStore() error {
	// TODO(jzt): we should move this to a utility package or something
	host, err := sys.UUID()
	if err != nil {
		log.Errorf("Failed to determine host UUID")
		return err
	}

	// attempt to create the image store if it doesn't exist
	store := &models.ImageStore{Name: host}
	_, err = portLayerClient.Storage.CreateImageStore(
		storage.NewCreateImageStoreParamsWithContext(ctx).WithBody(store),
	)

	if err != nil {
		if _, ok := err.(*storage.CreateImageStoreConflict); ok {
			log.Debugf("Store already exists")
			return nil
		}
		return err
	}
	log.Infof("Image store created successfully")
	return nil
}
コード例 #11
0
ファイル: image.go プロジェクト: vmware/vic
// TODO fix the errors so the client doesnt print the generic POST or DELETE message
func (i *Image) ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error) {
	defer trace.End(trace.Begin(imageRef))

	var deleted []types.ImageDelete
	var userRefIsID bool
	var imageRemoved bool

	// Use the image cache to go from the reference to the ID we use in the image store
	img, err := cache.ImageCache().Get(imageRef)
	if err != nil {
		return nil, err
	}

	// Get the tags from the repo cache for this image
	// TODO: remove this -- we have it in the image above
	tags := cache.RepositoryCache().Tags(img.ImageID)

	// did the user pass an id or partial id
	userRefIsID = cache.ImageCache().IsImageID(imageRef)
	// do we have any reference conflicts
	if len(tags) > 1 && userRefIsID && !force {
		t := uid.Parse(img.ImageID).Truncate()
		return nil,
			fmt.Errorf("conflict: unable to delete %s (must be forced) - image is referenced in one or more repositories", t)
	}

	// if we have an ID or only 1 tag lets delete the vmdk(s) via the PL
	if userRefIsID || len(tags) == 1 {
		log.Infof("Deleting image via PL %s (%s)", img.ImageID, img.ID)

		// needed for image store
		host, err := sys.UUID()
		if err != nil {
			return nil, err
		}

		params := storage.NewDeleteImageParamsWithContext(ctx).WithStoreName(host).WithID(img.ID)
		// TODO: This will fail if any containerVMs are referencing the vmdk - vanilla docker
		// allows the removal of an image (via force flag) even if a container is referencing it
		// should vic?
		_, err = PortLayerClient().Storage.DeleteImage(params)
		if err != nil {
			switch err := err.(type) {
			case *storage.DeleteImageLocked:
				return nil, fmt.Errorf("Failed to remove image %q: %s", imageRef, err.Payload.Message)
			default:
				return nil, err
			}
		}

		// we've deleted the image so remove from cache
		cache.ImageCache().RemoveImageByConfig(img)
		imagec.LayerCache().Remove(img.ID)
		imageRemoved = true

	} else {

		// only untag the ref supplied
		n, err := reference.ParseNamed(imageRef)
		if err != nil {
			return nil, fmt.Errorf("unable to parse reference(%s): %s", imageRef, err.Error())
		}
		tag := reference.WithDefaultTag(n)
		tags = []string{tag.String()}
	}
	// loop thru and remove from repoCache
	for i := range tags {
		// remove from cache, but don't save -- we'll do that afer all
		// updates
		refNamed, _ := cache.RepositoryCache().Remove(tags[i], false)
		dd := types.ImageDelete{Untagged: refNamed}
		deleted = append(deleted, dd)
	}

	// save repo now -- this will limit the number of PL
	// calls to one per rmi call
	err = cache.RepositoryCache().Save()
	if err != nil {
		return nil, fmt.Errorf("Untag error: %s", err.Error())
	}

	if imageRemoved {
		imageDeleted := types.ImageDelete{Deleted: img.ImageID}
		deleted = append(deleted, imageDeleted)
	}

	return deleted, err
}
コード例 #12
0
ファイル: imagec.go プロジェクト: kjplatz/vic
func main() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Fprintf(os.Stderr, string(sf.FormatError(fmt.Errorf("%s : %s", r, debug.Stack()))))
		}
	}()

	if version.Show() {
		fmt.Fprintf(os.Stdout, "%s\n", version.String())
		return
	}

	// Enable profiling if mode is set
	switch options.profiling {
	case "cpu":
		defer profile.Start(profile.CPUProfile, profile.ProfilePath("."), profile.Quiet).Stop()
	case "mem":
		defer profile.Start(profile.MemProfile, profile.ProfilePath("."), profile.Quiet).Stop()
	case "block":
		defer profile.Start(profile.BlockProfile, profile.ProfilePath("."), profile.Quiet).Stop()
	default:
		// do nothing
	}

	// Register our custom Error hook
	log.AddHook(NewErrorHook(os.Stderr))

	// Enable runtime tracing if tracing is true
	if options.tracing {
		tracing, err := os.Create(time.Now().Format("2006-01-02T150405.pprof"))
		if err != nil {
			log.Fatalf("Failed to create tracing logfile: %s", err)
		}
		defer tracing.Close()

		if err := trace.Start(tracing); err != nil {
			log.Fatalf("Failed to start tracing: %s", err)
		}
		defer trace.Stop()
	}

	// Open the log file
	f, err := os.OpenFile(options.logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatalf("Failed to open the logfile %s: %s", options.logfile, err)
	}
	defer f.Close()

	// Initiliaze logger with default TextFormatter
	log.SetFormatter(&log.TextFormatter{DisableColors: true, FullTimestamp: true})

	// Set the log level
	if options.debug {
		log.SetLevel(log.DebugLevel)
	}

	// SetOutput to log file and/or stdout
	log.SetOutput(f)
	if options.stdout {
		log.SetOutput(io.MultiWriter(os.Stdout, f))
	}

	// Parse the -reference parameter
	if err = ParseReference(); err != nil {
		log.Fatalf(err.Error())
	}

	// Host is either the host's UUID (if run on vsphere) or the hostname of
	// the system (if run standalone)
	host, err := sys.UUID()
	if host != "" {
		log.Infof("Using UUID (%s) for imagestore name", host)
	} else if options.standalone {
		host, err = os.Hostname()
		log.Infof("Using host (%s) for imagestore name", host)
	}

	if err != nil {
		log.Fatalf("Failed to return the UUID or host name: %s", err)
	}

	if !options.standalone {
		log.Debugf("Running with portlayer")

		// Ping the server to ensure it's at least running
		ok, err := PingPortLayer()
		if err != nil || !ok {
			log.Fatalf("Failed to ping portlayer: %s", err)
		}
	} else {
		log.Debugf("Running standalone")
	}

	// Calculate (and overwrite) the registry URL and make sure that it responds to requests
	options.registry, err = LearnRegistryURL(options)
	if err != nil {
		log.Fatalf("Error while pulling image: %s", err)
	}

	// Get the URL of the OAuth endpoint
	url, err := LearnAuthURL(options)
	if err != nil {
		log.Fatalf("Failed to obtain OAuth endpoint: %s", err)
	}

	// Get the OAuth token - if only we have a URL
	if url != nil {
		token, err := FetchToken(url)
		if err != nil {
			log.Fatalf("Failed to fetch OAuth token: %s", err)
		}
		options.token = token
	}

	// HACK: Required to learn the name of the vmdk from given reference
	// Used by docker personality until metadata support lands
	if !options.resolv {
		progress.Message(po, "", "Pulling from "+options.image)
	}

	// Get the manifest
	manifest, err := FetchImageManifest(options)
	if err != nil {
		if strings.Contains(err.Error(), "image not found") {
			log.Fatalf("Error: image %s not found", options.image)
		} else {
			log.Fatalf("Error while pulling image manifest: %s", err)
		}
	}

	// Create the ImageWithMeta slice to hold Image structs
	images, imageLayer, err := ImagesToDownload(manifest, host)
	if err != nil {
		log.Fatalf(err.Error())
	}

	// HACK: Required to learn the name of the vmdk from given reference
	// Used by docker personality until metadata support lands
	if options.resolv {
		if len(images) > 0 {
			fmt.Printf("%s", images[0].meta)
			os.Exit(0)
		}
		os.Exit(1)
	}

	// Fetch the blobs from registry
	if err := DownloadImageBlobs(images); err != nil {
		log.Fatalf(err.Error())
	}

	if err := CreateImageConfig(images, manifest); err != nil {
		log.Fatalf(err.Error())
	}

	// Write blobs to the storage layer
	if err := WriteImageBlobs(images); err != nil {
		log.Fatalf(err.Error())
	}

	if err := updateImageMetadata(imageLayer, manifest); err != nil {
		log.Fatalf(err.Error())
	}

	progress.Message(po, "", "Digest: "+manifest.Digest)
	if len(images) > 0 {
		progress.Message(po, "", "Status: Downloaded newer image for "+options.image+":"+options.tag)
	} else {
		progress.Message(po, "", "Status: Image is up to date for "+options.image+":"+options.tag)
	}
}
コード例 #13
0
ファイル: vm_test.go プロジェクト: vmware/vic
func TestVMAttributes(t *testing.T) {

	ctx := context.Background()

	session := test.Session(ctx, t)
	defer session.Logout(ctx)

	host := test.PickRandomHost(ctx, session, t)

	uuid, err := sys.UUID()
	if err != nil {
		t.Fatalf("unable to get UUID for guest - used for VM name: %s", err)
		return
	}
	ID := fmt.Sprintf("%s-%d", uuid, rand.Intn(math.MaxInt32))

	moref, err := CreateVM(ctx, session, host, ID)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}
	// Wrap the result with our version of VirtualMachine
	vm := NewVirtualMachine(ctx, session, *moref)

	folder, err := vm.FolderName(ctx)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}

	name, err := vm.Name(ctx)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}
	assert.Equal(t, name, folder)
	task, err := vm.PowerOn(ctx)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}
	_, err = task.WaitForResult(ctx, nil)
	if err != nil {
		t.Fatalf("ERROR: %s", err)
	}

	if guest, err := vm.FetchExtraConfig(ctx); err != nil {
		t.Fatalf("ERROR: %s", err)
	} else {
		assert.NotEmpty(t, guest)
	}
	defer func() {
		// Destroy the vm
		task, err := vm.PowerOff(ctx)
		if err != nil {
			t.Fatalf("ERROR: %s", err)
		}
		_, err = task.WaitForResult(ctx, nil)
		if err != nil {
			t.Fatalf("ERROR: %s", err)
		}
		task, err = vm.Destroy(ctx)
		if err != nil {
			t.Fatalf("ERROR: %s", err)
		}
		_, err = task.WaitForResult(ctx, nil)
		if err != nil {
			t.Fatalf("ERROR: %s", err)
		}
	}()
}
コード例 #14
0
ファイル: imagec.go プロジェクト: vmware/vic
// PullImage pulls an image from docker hub
func (ic *ImageC) PullImage() error {

	// ctx
	ctx, cancel := context.WithTimeout(ctx, ic.Options.Timeout)
	defer cancel()

	// Parse the -reference parameter
	if err := ic.ParseReference(); err != nil {
		log.Errorf(err.Error())
		return err
	}

	// Host is either the host's UUID (if run on vsphere) or the hostname of
	// the system (if run standalone)
	host, err := sys.UUID()
	if err != nil {
		log.Errorf("Failed to return host name: %s", err)
		return err
	}

	if host != "" {
		log.Infof("Using UUID (%s) for imagestore name", host)
	}

	ic.Storename = host

	// Ping the server to ensure it's at least running
	ok, err := PingPortLayer(ic.Host)
	if err != nil || !ok {
		log.Errorf("Failed to ping portlayer: %s", err)
		return err
	}

	// Calculate (and overwrite) the registry URL and make sure that it responds to requests
	ic.Registry, err = LearnRegistryURL(ic.Options)
	if err != nil {
		log.Errorf("Error while pulling image: %s", err)
		return err
	}

	// Get the URL of the OAuth endpoint
	url, err := LearnAuthURL(ic.Options)
	if err != nil {
		log.Infof(err.Error())
		switch err := err.(type) {
		case urlfetcher.ImageNotFoundError:
			return fmt.Errorf("Error: image %s not found", ic.Reference)
		default:
			return fmt.Errorf("Failed to obtain OAuth endpoint: %s", err)
		}
	}

	// Get the OAuth token - if only we have a URL
	if url != nil {
		token, err := FetchToken(ctx, ic.Options, url, ic.progressOutput)
		if err != nil {
			log.Errorf("Failed to fetch OAuth token: %s", err)
			return err
		}
		ic.Token = token
	}

	progress.Message(ic.progressOutput, "", "Pulling from "+ic.Image)

	// Get the manifest
	manifest, err := FetchImageManifest(ctx, ic.Options, ic.progressOutput)
	if err != nil {
		log.Infof(err.Error())
		switch err := err.(type) {
		case urlfetcher.ImageNotFoundError:
			return fmt.Errorf("Error: image %s not found", ic.Image)
		case urlfetcher.TagNotFoundError:
			return fmt.Errorf("Tag %s not found in repository %s", ic.Tag, ic.Image)
		default:
			return fmt.Errorf("Error while pulling image manifest: %s", err)
		}
	}

	ic.ImageManifest = manifest
	layers, err := ic.LayersToDownload()
	if err != nil {
		return err
	}
	ic.ImageLayers = layers

	err = ldm.DownloadLayers(ctx, ic)
	if err != nil {
		return err
	}

	return nil
}