示例#1
0
/*
周期性的检查到MongoDB的连接
如果检查失败,则尝试重新连接
*/
func TouchMongoDB(show_check_info bool) {
	c := time.Tick(10 * time.Second)
	for _ = range c {
		if MgoSession != nil && MgoDatabase != nil {
			err := MgoSession.Ping()
			if err != nil {
				// 当MongoDB无法连接时,关闭Session
				if MgoSession != nil && MgoDatabase == nil {
					utils.Println("MongoDB connection lost, clear resources and close session.")
					MgoDatabase.Logout()
					MgoSession.LogoutAll()
					MgoSession.Close()
					MgoDatabase = nil
					MgoSession = nil
				}
				SetMgoFailed()
				utils.Println("Check connection: MongoDB has gone, try to reconnect.")
				InitMongoDB(MgoURL, MgoTimeout)
			} else {
				SetMgoOK()

				if show_check_info == true {
					utils.Println("Check MongoDB connection... OK")
				}
			}
		} else {
			SetMgoFailed()
			utils.Println("Check connection: MongoDB has gone, try to reconnect.")
			InitMongoDB(MgoURL, MgoTimeout)
		}
	}
}
示例#2
0
func GetConn(host, port string) (*libvirt.VirConnection, error) {
	var conn *libvirt.VirConnection
	var err error
	var ok bool

	global_conn.lock.RLock()
	if conn, ok = global_conn.conn_map[host]; ok {
		if ok, err = conn.IsAlive(); ok {
			global_conn.lock.RUnlock()
			return conn, nil
		}
	}
	global_conn.lock.RUnlock()

	address := host + ":" + port
	new_conn, err := libvirt.NewVirConnection("qemu+tcp://" + address + "/system")
	if err != nil {
		return &new_conn, err
	}

	if v, ok := event_map[address]; !ok {
		if v == false {
			utils.Println("register event...")

			var Callback libvirt.DomainEventCallback
			Callback = EventCallback

			test := func() {}
			//dom := libvirt.VirDomain{}
			dom, _ := new_conn.LookupDomainByName("i-2-161-VM")

			ret := new_conn.DomainEventRegister(dom, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, &Callback, test)
			utils.Println("LIFECYCLE ret:", ret)

			//ret = new_conn.DomainEventRegister(dom, libvirt.VIR_DOMAIN_EVENT_ID_REBOOT, &Callback, test)
			//utils.Println("ret:", ret)

			//ret = new_conn.DomainEventRegister(dom, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB, &Callback, test)
			//utils.Println("ret:", ret)

			go func() {
				for {
					ret := libvirt.EventRunDefaultImpl()
					utils.Println("EventRunDefaultImpl ret:", ret)
				}
			}()

			event_map[address] = true
		}
	}

	global_conn.lock.Lock()
	global_conn.conn_map[host] = &new_conn
	global_conn.lock.Unlock()

	return &new_conn, nil
}
示例#3
0
func (this *Client) Close() {
	err := this.GetClient().Close()
	if err != nil {
		utils.Println(err)
	}
	this.InternalClient = nil
	this.Connected = false
	if this.Debug {
		utils.Println("Connection closed.")
	}
}
示例#4
0
// POSIX信号发生时的回调
func SignalCallback() {
	for s := range SignalChan {
		sig := s.String()
		utils.Println("Got Signal: ", sig)

		if s == syscall.SIGINT {
			utils.Println("RConsole server exit...")
			os.Exit(0)
		}
	}
}
示例#5
0
func (this *Client) ReadInstruction() *inst.Instruction {
	if this.Debug {
		utils.Println("Read instruction")
	}
	instruction, err := inst.LoadInstruction(this.BufReceive())
	if this.Debug {
		utils.Println(instruction.String())
	}
	if err != nil {
		utils.Println("Read instruction failed:", err)
	} else {
		return instruction
	}
	return nil
}
示例#6
0
func (this *Client) Send(data []byte) error {
	if this.Debug {
		utils.Printf("Sending data: %s\n", string(data))
	}
	client := this.GetClient()
	if client == nil {
		return fmt.Errorf("maybe not connected\n")
	}
	n, err := client.Write(data)
	if err != nil {
		utils.Println("Send data failed:", err)
		this.Close()
		return err
	}
	if n != len(data) {
		utils.Println("Write() has blocked, send: %d, all: %d", n, len(data))
		this.Close()
		return fmt.Errorf("Write() has blocked, send: %d, all: %d", n, len(data))
	}

	return nil
}
示例#7
0
func (this *HostController) Post() {
	var resp_message ResponseMessage
	var libvirt_host LibvirtHost
	var insert_id string

	err := this.ParseForm(&libvirt_host)
	if err != nil {
		err_msg := fmt.Sprintf("parseform failed: %s", err)
		utils.Println(err_msg)
		resp_message.Code = 1
		resp_message.Message = err_msg
		this.Ctx.Output.Status = 500
		goto end
	}

	err = this.Valid(libvirt_host)
	if err != nil {
		err_msg := fmt.Sprintf("validation failed: %s", err)
		utils.Println(err_msg)
		resp_message.Code = 2
		resp_message.Message = err_msg
		this.Ctx.Output.Status = 500
		goto end
	}

	libvirt_host.UUID = utils.MakeRandomID()
	insert_id = libvirt_host.UUID
	err = mongo.InsertOne("libvirt_host", libvirt_host)

	if resp_message.Code == 0 {
		resp_message.Code = 0
		resp_message.Message = insert_id
	}

end:
	this.Data["json"] = resp_message
	this.ServeJson()
}
示例#8
0
func (this *Client) GetClient() net.Conn {
	if this.InternalClient == nil {
		address := net.JoinHostPort(this.Host, this.Port)
		conn, err := net.DialTimeout("tcp", address, this.Timeout)
		if err != nil {
			utils.Println(err)
			return nil
		}

		this.InternalClient = conn
		this.BufReader = bufio.NewReader(conn)
		this.BufWriter = bufio.NewWriter(conn)

		if this.Debug {
			utils.Printf("Client connected with gucad server (%s %s %s)\n",
				this.Host, this.Port, this.Timeout)
		}
		return this.InternalClient
	}

	return this.InternalClient
}
示例#9
0
func (this *ConnectionManagerController) CreateConnection() {
	var resp_message ResponseMessage
	var found_protocol bool
	var decode_failed bool
	var decode_failed_reason string
	var insert_failed bool
	var insert_failed_reason string
	var insert_id string
	var valid_failed bool
	var valid_failed_reason string

	conn_type := this.Ctx.Input.Param(":conn_type")

	found_protocol = client.ValidProtocol(conn_type)

	if found_protocol {

		if conn_type == "vnc" {
			args, err := this.DecodeVNCArgs()
			if err != nil {
				decode_failed = true
				decode_failed_reason = fmt.Sprintf("decode vnc args failed: %s", err)
			} else {
				err = this.Valid(args)
				if err != nil {
					valid_failed = true
					valid_failed_reason = fmt.Sprintf("valid error: %s", err)
				} else {
					args.UUID = utils.MakeRandomID()
					insert_id = args.UUID
					err = mongo.InsertOne("connection", *args)
					if err != nil {
						insert_failed = true
						insert_failed_reason = fmt.Sprintf("save vnc args failed: %s, args: %s", err, *args)
					}
				}
			}
		}

		if conn_type == "rdp" {
			args, err := this.DecodeRDPArgs()
			if err != nil {
				decode_failed = true
				decode_failed_reason = fmt.Sprintf("decode rdp args failed: %s", err)
			} else {
				err = this.Valid(args)
				if err != nil {
					valid_failed = true
					valid_failed_reason = fmt.Sprintf("valid error: %s", err)
				} else {
					args.UUID = utils.MakeRandomID()
					insert_id = args.UUID
					err = mongo.InsertOne("connection", *args)
					if err != nil {
						insert_failed = true
						insert_failed_reason = fmt.Sprintf("save rdp args failed: %s, args: %s", err, *args)
					}
				}
			}
		}

		if conn_type == "ssh" {
			args, err := this.DecodeSSHArgs()
			if err != nil {
				decode_failed = true
				decode_failed_reason = fmt.Sprintf("decode ssh args failed: %s", err)
			} else {
				err = this.Valid(args)
				if err != nil {
					valid_failed = true
					valid_failed_reason = fmt.Sprintf("valid error: %s", err)
				} else {
					args.UUID = utils.MakeRandomID()
					insert_id = args.UUID
					err = mongo.InsertOne("connection", *args)
					if err != nil {
						insert_failed = true
						insert_failed_reason = fmt.Sprintf("save ssh args failed: %s, args: %s", err, *args)
					}
				}
			}
		}

		if conn_type == "telnet" {
			args, err := this.DecodeTELNETArgs()
			if err != nil {
				decode_failed = true
				decode_failed_reason = fmt.Sprintf("decode telnet args failed: %s", err)
			} else {
				err = this.Valid(args)
				if err != nil {
					valid_failed = true
					valid_failed_reason = fmt.Sprintf("valid error: %s", err)
				} else {
					args.UUID = utils.MakeRandomID()
					insert_id = args.UUID
					err = mongo.InsertOne("connection", *args)
					if err != nil {
						insert_failed = true
						insert_failed_reason = fmt.Sprintf("save telnet args failed: %s, args: %s", err, *args)
					}
				}
			}
		}

		if conn_type == "spice" {
			args, err := this.DecodeSPICEArgs()
			if err != nil {
				decode_failed = true
				decode_failed_reason = fmt.Sprintf("decode spice args failed: %s", err)
			} else {
				err = this.Valid(args)
				if err != nil {
					valid_failed = true
					valid_failed_reason = fmt.Sprintf("valid error: %s", err)
				} else {
					args.UUID = utils.MakeRandomID()
					insert_id = args.UUID
					err = mongo.InsertOne("connection", *args)
					if err != nil {
						insert_failed = true
						insert_failed_reason = fmt.Sprintf("save spice args failed: %s, args: %s", err, *args)
					}
				}
			}
		}

		if conn_type == "libvirt" {
			args, err := this.DecodeLIBVIRTArgs()
			if err != nil {
				decode_failed = true
				decode_failed_reason = fmt.Sprintf("decode libvirt args failed: %s", err)
			} else {
				err = this.Valid(args)
				if err != nil {
					valid_failed = true
					valid_failed_reason = fmt.Sprintf("valid error: %s", err)
				} else {
					args.UUID = utils.MakeRandomID()
					insert_id = args.UUID
					err = mongo.InsertOne("connection", *args)
					if err != nil {
						insert_failed = true
						insert_failed_reason = fmt.Sprintf("save libvirt args failed: %s, args: %s", err, *args)
					}
				}
			}
		}

		if decode_failed {
			utils.Println(decode_failed_reason)
			resp_message.Code = 1
			resp_message.Message = decode_failed_reason
			this.Ctx.Output.Status = 500
		}

		if insert_failed {
			utils.Println(insert_failed_reason)
			resp_message.Code = 2
			resp_message.Message = insert_failed_reason
			this.Ctx.Output.Status = 500
		}

		if valid_failed {
			utils.Println(valid_failed_reason)
			resp_message.Code = 3
			resp_message.Message = valid_failed_reason
			this.Ctx.Output.Status = 500
		}

	} else {
		resp_message.Code = 4
		resp_message.Message = "wrong protocol type"
		this.Ctx.Output.Status = 400
	}

	if resp_message.Code == 0 {
		resp_message.Code = 0
		resp_message.Message = insert_id
	}

	this.Data["json"] = resp_message
	this.ServeJson()
}
示例#10
0
func EventCallback(c *libvirt.VirConnection, d *libvirt.VirDomain, event interface{}, f func()) int {
	utils.Println("got event:", c, d, event, f)
	return 0
}
示例#11
0
func (this *Client) HandShake(protocol, width, height, dpi string, audio []string, video []string, KWArgs map[string]string) bool {
	var found_protocol bool
	for index := range PROTOCOLS {
		if protocol == PROTOCOLS[index] {
			found_protocol = true
			break
		}
	}
	if !found_protocol {
		utils.Printf("Invalid protocol: %s\n", protocol)
		return false
	}

	// 1. Send "select" instruction
	utils.Println("Send 'select' instruction")
	err := this.SendInstruction(inst.NewInstruction("select", protocol))
	if err != nil {
		utils.Println("Send 'select' failed:", err)
		return false
	}

	// 2. Receive "args" instruction
	instruction := this.ReadInstruction()
	utils.Printf("Expecting 'args' instruction, received: %s\n", instruction.String())

	if instruction == nil {
		utils.Println("Cannot establish Handshake. Connection Lost!")
		return false
	}

	if instruction.OpCode != "args" {
		utils.Printf("Cannot establish Handshake. Expected opcode 'args', received '%s' instead.\n", instruction.OpCode)
		return false
	}

	// 3. Respond with size, audio & video support
	utils.Printf("Send 'size' instruction (%s %s %s)\n", width, height, dpi)
	size_instruction := inst.NewInstruction("size", width, height, dpi)
	err = this.SendInstruction(size_instruction)
	if err != nil {
		utils.Println("Send 'size' failed:", err)
		return false
	}

	utils.Printf("Send 'audio' instruction (%s)\n", audio)
	err = this.SendInstruction(inst.NewInstruction("audio", audio...))
	if err != nil {
		utils.Println("Send 'audio' failed:", err)
		return false
	}

	utils.Printf("Send 'video' instruction (%s)\n", video)
	err = this.SendInstruction(inst.NewInstruction("video", video...))
	if err != nil {
		utils.Println("Send 'video' failed:", err)
		return false
	}

	var connect_args []string
	for idx := range instruction.Args {
		arg := strings.Replace(instruction.Args[idx], "-", "_", -1)
		if v, ok := KWArgs[arg]; ok {
			connect_args = append(connect_args, v)
		} else {
			connect_args = append(connect_args, "")
		}
	}

	// 4. Send connect arguments
	utils.Printf("Send 'connect' instruction (%s)\n", connect_args)
	err = this.SendInstruction(inst.NewInstruction("connect", connect_args...))
	if err != nil {
		utils.Println("Send 'connect' failed:", err)
		return false
	}

	return true
}
示例#12
0
func (this *Client) SendInstruction(instruction *inst.Instruction) error {
	if this.Debug {
		utils.Println("Sending instruction:", instruction.String())
	}
	return this.Send([]byte(instruction.Encode()))
}
示例#13
0
/*
判断命令行参数和配置文件
如果配置文件不存在,则会使用命令行的参数
否则直接使用配置文件中的参数
*/
func Init() {
	if *ServerProfile == true {
		Config.ServerProfile = true
	}

	if !Exist(*ConfigFile) {
		if *LogFile == "" {
			*LogFile = "/var/log/rconsole.log"
		}
		Config.LogFile = *LogFile

		if *ProfileAddress == "" {
			*ProfileAddress = "0.0.0.0:9998"
		}
		Config.ProfileAddress = *ProfileAddress

		if *ListenAddress == "" {
			*ListenAddress = "0.0.0.0:9999"
		}
		Config.ListenAddress = *ListenAddress

		if *MongoURL == "" {
			*MongoURL = "mongo://127.0.0.1/rconsole"
		}
		Config.MongoURL = *MongoURL

		if *MongoTimeout == 0 {
			*MongoTimeout = 1
		}
		Config.MongoTimeout = *MongoTimeout

		if *ShowCheckConn == true {
			*ShowCheckConn = true
		}
		Config.ShowCheckConn = *ShowCheckConn

		if *ServerDebug == true {
			*ServerDebug = true
		}
		Config.ServerDebug = *ServerDebug

	} else {
		data, err := ioutil.ReadFile(*ConfigFile)
		if err != nil {
			utils.Println(err)
			return
		}

		err = json.Unmarshal(data, &Config)
		if err != nil {
			utils.Println(err)
		}

		if *LogFile != "" {
			Config.LogFile = *LogFile
		}

		if *ProfileAddress != "" {
			Config.ProfileAddress = *ProfileAddress
		}

		if *ListenAddress != "" {
			Config.ListenAddress = *ListenAddress
		}

		if *MongoURL != "" {
			Config.MongoURL = *MongoURL
		}

		if *MongoTimeout != 0 {
			Config.MongoTimeout = *MongoTimeout
		}

		if *ShowCheckConn != false {
			Config.ShowCheckConn = *ShowCheckConn
		}

		if *ServerDebug != false {
			Config.ServerDebug = *ServerDebug
		}
	}
}
示例#14
0
func main() {
	ret := libvirt.EventRegisterDefaultImpl()
	utils.Println("EventRegisterDefaultImpl ret:", ret)

	runtime.GOMAXPROCS(runtime.NumCPU())

	defer func() {
		if err := recover(); err != nil {
			utils.Println("Server Error: ", err.(string))
		}
	}()

	// 解析命令行参数
	flag.Parse()

	// 自定义初始化
	Init()

	// 设置guacd客户端连接时的调试信息
	client.ClientDebug = Config.ServerDebug

	// 初始化guacd服务连接池
	client.Pool.Init(Config.GuacdServer)

	utils.Println("Try connect to:", Config.MongoURL)

	// 初始化MongoDB的连接
	timeout := time.Duration(Config.MongoTimeout) * time.Second
	err := mongo.InitMongoDB(Config.MongoURL, timeout)
	if err != nil {
		utils.Println(err)
		os.Exit(1)
	}

	// 启动独立的线程测试MongoDB连接
	go mongo.TouchMongoDB(Config.ShowCheckConn)

	utils.Println("Connect to MongoDB OK")

	// 捕捉信号并设置回调函数
	SignalChan = make(chan os.Signal, 1)
	signal.Notify(SignalChan,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT,
		syscall.SIGPIPE,
		syscall.SIGALRM,
		syscall.SIGPIPE)

	go SignalCallback()

	// 启动性能调试接口
	if Config.ServerProfile == true {
		go func() {
			http.ListenAndServe(Config.ProfileAddress, nil)
		}()
	}

	utils.Printf("http profile server Running on %s\n", Config.ProfileAddress)

	addr_splited := strings.Split(Config.ListenAddress, ":")
	if len(addr_splited) < 2 {
		utils.Println("the format of listen address is invalid!")
		os.Exit(1)
	}

	beego.HttpAddr = addr_splited[0]
	beego.HttpPort, err = strconv.Atoi(addr_splited[1])

	beego.SetStaticPath("/static", "./static")
	beego.Router("/connect", &controllers.MainController{})
	beego.Router("/ws", &wscontrollers.WebSocketController{})
	beego.Router("/ws/spice", &spicecontrollers.SpiceController{})
	beego.Router("/ws/libvirt", &libvirtcontrollers.LibvirtController{})

	beego.Router("/api/conn/list", &managercontrollers.ConnectionManagerController{}, "get:ListConnection")
	beego.Router("/api/conn/create/:conn_type([a-z]+)", &managercontrollers.ConnectionManagerController{}, "post:CreateConnection")
	beego.Router("/api/conn/update/:conn_type([a-z]+)", &managercontrollers.ConnectionManagerController{}, "put:UpdateConnection")
	beego.Router("/api/conn/delete", &managercontrollers.ConnectionManagerController{}, "delete:DeleteConnection")

	beego.Router("/api/libvirt/host", &libvirtcontrollers.HostController{})

	beego.Run()
}
示例#15
0
func (this *SpiceController) Get() {
	ws, err := upgrader.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request, nil)
	if err != nil {
		utils.Println("websocket upgrade failed:", err)
		return
	}

	defer func() {
		utils.Println("websocket client disconnected:", ws.RemoteAddr())
		ws.Close()
	}()

	Type := this.GetString("type")

	if Type != "spice" {
		utils.Printf("invalid protocol: %s\n", Type)
		return
	}

	spice_args, err := GetSPICEArgs(this.Ctx)
	if err != nil {
		utils.Println("get args for SPICE failed:", err)
		return
	}

	if spice_args == nil {
		utils.Println("empty args for SPICE")
		return
	}

	hostname := spice_args["hostname"]
	port := spice_args["port"]

	spice_conn, err := net.DialTimeout("tcp", hostname+":"+port, 3*time.Second)
	if err != nil {
		utils.Println("Can not connect to spice server:", err)
		return
	}

	writer_buf := make([]byte, 4096)

	go func() {
		for {
			n, err := spice_conn.Read(writer_buf)
			if err != nil {
				utils.Println("Error read from spice server:", err)
				return
			}

			err = ws.WriteMessage(websocket.BinaryMessage, writer_buf[:n])
			if err != nil {
				utils.Println("websocket write failed:", err)
				return
			}
		}
	}()

	// TODO: use ws.NextReader to reuse memory allocation

	for {
		_, data, err := ws.ReadMessage()
		if err != nil {
			utils.Println("websocket readmessage failed:", err)
			return
		}

		spice_conn.Write(data)
	}
}
示例#16
0
func (this *LibvirtController) Get() {
	var console_host string
	var console_port string
	ws, err := upgrader.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request, nil)
	if err != nil {
		utils.Println("websocket upgrade failed:", err)
		return
	}

	defer func() {
		utils.Println("websocket client disconnected:", ws.RemoteAddr())
		ws.Close()
	}()

	libvirt_args, err := GetLIBVIRTArgs(this.Ctx)
	if err != nil {
		utils.Println(err)
		return
	}

	if libvirt_args == nil {
		utils.Println("empty args for LIBVIRT")
		return
	}

	libvirt_host := libvirt_args["hostname"]
	libvirt_port := libvirt_args["port"]
	vm_name := libvirt_args["vm"]

	graphics, err := libvirt.GetDomainGraphics(libvirt_host, libvirt_port, vm_name)
	if err != nil {
		utils.Println(err)
		return
	}

	if graphics.Listen.Address == "0.0.0.0" {
		console_host = libvirt_host
	} else {
		console_host = graphics.Listen.Address
	}

	console_port = graphics.Port

	console_conn, err := net.DialTimeout("tcp", console_host+":"+console_port, 3*time.Second)
	if err != nil {
		utils.Println("Can not connect to console host:", err)
		return
	}

	writer_buf := make([]byte, 4096)

	go func() {
		for {
			n, err := console_conn.Read(writer_buf)
			if err != nil {
				utils.Println("Error read from console host:", err)
				return
			}

			err = ws.WriteMessage(websocket.BinaryMessage, writer_buf[:n])
			if err != nil {
				utils.Println("websocket write failed:", err)
				return
			}
		}
	}()

	// TODO: use ws.NextReader to reuse memory allocation

	for {
		_, data, err := ws.ReadMessage()
		if err != nil {
			utils.Println("websocket readmessage failed:", err)
			return
		}

		console_conn.Write(data)
	}
}