Beispiel #1
0
func SendLocalToRemote(stream libvirt.VirStream, volume libvirt.VirStorageVol, data []byte) error {

	err := libvirt.StorageVolUpload(volume, stream, 0, uint64(len(data)))
	if err != nil {
		return err
	}
	//transfter volume
	remain := len(data)
	sent := 0
	offset := 0
	DATALEN := 16384
	for remain > 0 {
		if remain > DATALEN {
			sent = stream.Send(data[offset:], DATALEN)
		} else {
			sent = stream.Send(data[offset:], remain)
		}

		if sent < 0 {
			stream.Abort()
			return errors.New("Stream Send return 0")
		}
		if sent == 0 {
			break
		}
		remain -= sent
		offset += sent

	}
	err = stream.Finish()
	if err != nil {
		return err
	}
	return nil

}
Beispiel #2
0
func VmInstall(conn libvirt.VirConnection, vmname string, url string, autoyast string, imageSize uint64, ch chan string) {

	//check input

	if len(vmname) <= 0 {
		reportFail(ch, "Name too short")
		return
	}

	if imageSize == 0 {
		reportFail(ch, "disk size too short")
	}

	//sender close the channel
	if ch != nil {
		defer close(ch)
	}

	pool, err := createRemoteBootPool(conn)
	defer pool.Free()

	//url := "http://mirror.bej.suse.com/dist/install/SLP/SLE-12-Server-Beta10/x86_64/DVD1"
	linuxSurfix := "/boot/x86_64/loader/linux"
	initrdSurfix := "/boot/x86_64/loader/initrd"

	// Download linux and initrd image from remote
	reportStatus(ch, "Downloading linux image")
	m := DownloadManager{}
	m.Regsiter(HTTPDownloader{})
	linuxContent, err := m.Download(url + linuxSurfix)
	if err != nil {
		reportFail(ch, err.Error())
		return
	}

	reportStatus(ch, "Downloading initrd image")

	initrdContent, err := m.Download(url + initrdSurfix)
	if err != nil {
		reportFail(ch, err.Error())
		return
	}

	//prepare two temporary name for linux;initrd image
	temp := generateFourRandom()
	bootImageName := vmname + temp + ".image"
	bootInitrdName := vmname + temp + ".initrd"

	// create remote boot linux storage from temp pool
	linuxVolume, err := createVolume(pool, Storage{Name: bootImageName, Size: uint64(len(linuxContent)), Type: "raw"})
	if err != nil {
		reportFail(ch, err.Error())
		return
	}
	defer linuxVolume.Free()
	defer linuxVolume.Delete()
	linuxPath, _ := linuxVolume.GetPath()

	// create remote boot initrd storage from temp pool
	initrdVolume, err := createVolume(pool, Storage{Name: bootInitrdName, Size: uint64(len(initrdContent)), Type: "raw"})
	if err != nil {
		reportFail(ch, err.Error())
		return
	}
	defer initrdVolume.Free()
	defer initrdVolume.Delete()
	initrdPath, _ := initrdVolume.GetPath()

	var stream libvirt.VirStream
	stream, err = conn.StreamNew()
	if err != nil {
		reportFail(ch, err.Error())
		return
	}
	defer stream.Free()

	//Upload to remote
	reportStatus(ch, "sending linuxVolume")
	if err := SendLocalToRemote(stream, linuxVolume, linuxContent); err != nil {
		reportFail(ch, err.Error())
		return
	}

	reportStatus(ch, "sending initrd")
	if err := SendLocalToRemote(stream, initrdVolume, initrdContent); err != nil {
		reportFail(ch, err.Error())
		return
	}

	// create image
	reportStatus(ch, "creating remote imaging...")
	dataPool, err := conn.StoragePoolLookupByName("default")
	if err != nil {
		reportFail(ch, err.Error())
		return
	}
	defer dataPool.Free()

	//var imageSize uint64 = 8589934592 //8G

	realImageName := vmname + ".img"
	imageVolume, err := createVolume(dataPool, Storage{Name: realImageName, Size: imageSize, Type: "qcow2"})

	if err != nil {
		reportFail(ch, err.Error())
		return
	}

	defer imageVolume.Free()
	imagePath, _ := imageVolume.GetPath()

	log.Println("Create remote VirtualMachine")
	reportStatus(ch, "Create remote VirtualMachine")

	// create boot xml
	var xml string
	// add autoyast
	var installArg string
	if len(autoyast) > 0 {
		installArg = url + " autoyast=" + autoyast
	} else {
		installArg = url
	}

	domain := Domain{Name: vmname, Kernel: linuxPath, Initrd: initrdPath, Image: imagePath, Install: installArg}
	if xml, err = domain.Encode(); err != nil {
		reportFail(ch, err.Error())
		return
	}

	// create booting vm
	bootingDomain, err := conn.CreateXML(xml)
	if err != nil {
		reportFail(ch, err.Error())
		return
	}
	defer bootingDomain.Free()

	// get xml from remote
	// create new defined xml
	if xml, err = bootingDomain.GetXMLDesc(); err != nil {
		reportFail(ch, err.Error())
		return
	}

	/* change xml a bit using regex lines, I do not want to parse the xml file
	* 1. change os section to boot from hd
	* 2. change destory section
	 */
	/* (?s) is used to let . match newline(\n) */
	osSection := regexp.MustCompile("(?s)<os>.*</os>")
	onBoot := regexp.MustCompile("(?s)<on_reboot>.*</on_reboot>")
	onCrash := regexp.MustCompile("(?s)<on_crash>.*</on_crash>")

	xml = osSection.ReplaceAllString(xml, OSSECTION)
	xml = onBoot.ReplaceAllString(xml, ONBOOT)
	xml = onCrash.ReplaceAllString(xml, ONCRASH)

	newPersistentDomain, err := conn.DefineXML(xml)
	if err != nil {
		reportFail(ch, err.Error())
		return
	}

	log.Println(newPersistentDomain)
	defer newPersistentDomain.Free()

	reportSuccess(ch)

}