Beispiel #1
0
func readLibvirtVM(HostIpAddress string, UUIDString string) (VirtualMachine, error) {
	var conn libvirt.VirConnection
	var err error
	ok := ipaddressConnectionCache.Check(HostIpAddress)
	if ok == false {
		conn, err = libvirt.NewVirConnection("qemu+ssh://root@" + HostIpAddress + "/system")
		if err != nil {
			return VirtualMachine{}, err
		}
		ipaddressConnectionCache.Set(HostIpAddress, conn)
	} else {
		//?How to deal with connection's not alive
		conn = ipaddressConnectionCache.Get(HostIpAddress).(libvirt.VirConnection)
		if ok, _ := conn.IsAlive(); !ok {
			log.Printf("remote %s is not alive", HostIpAddress)
			conn, err = libvirt.NewVirConnection("qemu+ssh://root@" + HostIpAddress + "/system")
			if err != nil {
				ipaddressConnectionCache.Delete(HostIpAddress)
				return VirtualMachine{}, err
			}
			/*TODO Write Lock*/
			ipaddressConnectionCache.Set(HostIpAddress, conn)
		}
	}

	domain, err := conn.LookupByUUIDString(UUIDString)
	if err != nil {
		return VirtualMachine{}, err
	}
	vm := fillVmData(domain, conn)

	return vm, nil
}
Beispiel #2
0
func registerRebootAndGetVncPort(name string, ip string, conn libvirt.VirConnection) string {
	var domain libvirt.VirDomain
	domain, err := conn.LookupByName(name)
	if err != nil {
		log.Println("FAIL: find running domain to start vncviewer")
		return ""
	}
	defer domain.Free()

	xmlData, _ := domain.GetXMLDesc()
	v := utils.ParseDomainXML(xmlData)

	/* to get VNC port */
	var vncPort string
	if v.Devices.Graphics.VNCPort == "-1" {
		log.Println("FAIL:Can not get vnc port")
		return ""
	}

	vncPort = v.Devices.Graphics.VNCPort

	ret := libvirt.ConnectDomainEventRegister(conn, domain, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, libvirt.LifeCycleCallBackType(myrebootcallback))
	if ret == -1 {
		fmt.Println("can not autoreboot")
	} else {
		callbackMap.Set(name, ret)
	}

	vncAddress := ip + ":" + vncPort
	//e.g. http://147.2.207.233/vnc_auto.html?title=lwang-n1-sle12rc1&path=websockify?ip=147.2.207.233:5902

	log.Println(fmt.Sprintf("/vnc_auto.html?title=%s&path=websockify?ip=%s", name, vncAddress))
	return fmt.Sprintf("/vnc_auto.html?title=%s&path=websockify?ip=%s", name, vncAddress)
}
Beispiel #3
0
func startVNCviewer(conn libvirt.VirConnection, name string, hostIPAddress string) {
	fmt.Println("would bring up vncviewer...")
	var domain libvirt.VirDomain
	domain, err := conn.LookupByName(name)
	if err != nil {
		fmt.Println("FAIL: find running domain to start vncviewer")
		return
	}
	defer domain.Free()

	xmlData, _ := domain.GetXMLDesc()
	v := utils.ParseDomainXML(xmlData)

	/* to get VNC port */
	var vncPort string
	if v.Devices.Graphics.VNCPort == "-1" {
		fmt.Println("FAIL:Can not get vnc port")
		return
	}

	vncPort = v.Devices.Graphics.VNCPort

	ret := libvirt.ConnectDomainEventRegister(conn, domain, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, libvirt.LifeCycleCallBackType(myrebootcallback))
	if ret == -1 {
		fmt.Println("can not autoreboot")
		return
	}

	fmt.Println("RUNNING: vncviewer " + hostIPAddress + ":" + vncPort)

	cmd := exec.Command("vncviewer", hostIPAddress+":"+vncPort)
	//Run will block
	err = cmd.Run()
	if err != nil {
		fmt.Println("FAIL:can not start vncviewer")
		fmt.Println(err)
		return
	}
	fmt.Println("vncviewer is quiting")
	time.Sleep(3 * time.Second)

	//re run vncviewer
	cmd.Run()

}
Beispiel #4
0
func createRemoteBootPool(conn libvirt.VirConnection) (libvirt.VirStoragePool, error) {
	// Test volume pool
	// create vol from pool and Upload
	var pool libvirt.VirStoragePool
	pool, err := conn.StoragePoolLookupByName("boot-scratch")
	if err != nil {
		// pool not existed
		// create on pool named "boot-scrath"
		// TODO
		log.Println("pool not exist")
		//poolXML, _:= ioutil.ReadFile("./pool.xml")
		poolXML := POOXML
		pool, err = conn.StoragePoolDefineXML(string(poolXML))
		if err != nil {
			return libvirt.VirStoragePool{}, err
		}
	}
	return pool, nil
}
Beispiel #5
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)

}
Beispiel #6
0
func readLibvirtPysicalMachine(hosts []*PhysicalMachine) {
	/* get libvirt connections */
	numLiveHost := 0
	var conn libvirt.VirConnection

	/* use this type in chanStruct */
	type connResult struct {
		host     *PhysicalMachine
		conn     libvirt.VirConnection
		existing bool
	}
	connChan := make(chan connResult)
	var numGoroutines = 0

	for _, host := range hosts {
		ok := ipaddressConnectionCache.Check(host.IpAddress)
		if ok == false {
			numGoroutines++
			go func(host *PhysicalMachine) {
				conn, err := libvirt.NewVirConnection("qemu+ssh://root@" + host.IpAddress + "/system")
				if err != nil {
					checkErr(err, fmt.Sprintf("failed to connect to %s", host.IpAddress))
					host.Existing = false
					connChan <- connResult{host: host, existing: false}
					return
				}
				connChan <- connResult{host: host, conn: conn, existing: true}
			}(host)
		} else {
			/* existing a conn which is alive */
			conn = ipaddressConnectionCache.Get(host.IpAddress).(libvirt.VirConnection)
			if ok, _ := conn.IsAlive(); ok {
				host.VirConn = conn
				host.Existing = true
				numLiveHost++
				/* existing a conn which is dead */
			} else {
				log.Printf("remove %s is not alive", host.IpAddress)
				host.Existing = false
				ipaddressConnectionCache.Delete(host.IpAddress)
				/* TODO ?if close the connectin */
				conn.CloseConnection()
			}
		}
	}

	for i := 0; i < numGoroutines; i++ {
		r := <-connChan
		if r.existing {
			r.host.VirConn = r.conn
			r.host.Existing = true
			/*Write Lock*/
			ipaddressConnectionCache.Set(r.host.IpAddress, r.conn)
			numLiveHost++
		}
	}

	/* all the PhysicalMachines are ready, VirConnection was connected now */
	/* receive data from VirConnections */

	done := make(chan bool)
	for _, host := range hosts {
		if host.Existing == false {
			continue
		}

		go func(host *PhysicalMachine) {
			domains, _ := host.VirConn.ListAllDomains()
			for _, virdomain := range domains {
				vm := fillVmData(virdomain, conn)
				vm.HostIpAddress = host.IpAddress
				if vm.Active == true {
					vm.VNCAddress = host.IpAddress
				}
				//will not have any operations on vm, virdomain could be freeed
				virdomain.Free()
				host.VirtualMachines = append(host.VirtualMachines, &vm)
			}
			done <- true
		}(host)
	}
	/* wait for all ListAllDomains finish */
	for i := 0; i < numLiveHost; i++ {
		<-done
	}

}