예제 #1
0
파일: attach.go 프로젝트: vmware/vic
func (t *attachServerSSH) globalMux(reqchan <-chan *ssh.Request) {
	defer trace.End(trace.Begin("attach server global request handler"))

	// to make sure we close the channel once
	var once sync.Once

	// ContainersReq will close this channel
	t.askedAndAnswered = make(chan struct{})

	for req := range reqchan {
		var pendingFn func()
		var payload []byte
		ok := true

		log.Infof("received global request type %v", req.Type)

		switch req.Type {
		case msgs.ContainersReq:
			keys := make([]string, len(t.config.Sessions))
			i := 0
			for k := range t.config.Sessions {
				keys[i] = k
				i++
			}
			msg := msgs.ContainersMsg{IDs: keys}
			payload = msg.Marshal()

			// unblock ^ (above)
			pendingFn = func() {
				once.Do(func() {
					close(t.askedAndAnswered)
				})
			}
		default:
			ok = false
			payload = []byte("unknown global request type: " + req.Type)
		}

		log.Debugf("Returning payload: %s", string(payload))

		// make sure that errors get send back if we failed
		if req.WantReply {
			log.Debugf("Sending global request reply %t back with %#v", ok, payload)
			if err := req.Reply(ok, payload); err != nil {
				log.Warnf("Failed to reply a global request back")
			}
		}

		// run any pending work now that a reply has been sent
		if pendingFn != nil {
			log.Debug("Invoking pending work for global mux")
			go pendingFn()
			pendingFn = nil
		}
	}
}
예제 #2
0
파일: client.go 프로젝트: vmware/vic
func SSHls(client *ssh.Client) ([]string, error) {
	defer trace.End(trace.Begin(""))

	ok, reply, err := client.SendRequest(msgs.ContainersReq, true, nil)
	if !ok || err != nil {
		return nil, fmt.Errorf("failed to get container IDs from remote: %s", err)
	}

	ids := msgs.ContainersMsg{}

	if err = ids.Unmarshal(reply); err != nil {
		log.Debugf("raw IDs response: %+v", reply)
		return nil, fmt.Errorf("failed to unmarshal ids from remote: %s", err)
	}

	return ids.IDs, nil
}
예제 #3
0
파일: attach.go 프로젝트: kjplatz/vic
func (t *attachServerSSH) globalMux(reqchan <-chan *ssh.Request) {
	defer trace.End(trace.Begin("start attach server global request handler"))

	for req := range reqchan {
		var pendingFn func()
		var payload []byte
		ok := true

		log.Infof("received global request type %v", req.Type)

		switch req.Type {
		case msgs.ContainersReq:
			keys := make([]string, len(t.config.Sessions))
			i := 0
			for k := range t.config.Sessions {
				keys[i] = k
				i++
			}
			msg := msgs.ContainersMsg{IDs: keys}
			payload = msg.Marshal()

		default:
			ok = false
			payload = []byte("unknown global request type: " + req.Type)
		}

		log.Debugf("Returning payload: %s", string(payload))

		// make sure that errors get send back if we failed
		if req.WantReply {
			req.Reply(ok, payload)
		}

		// run any pending work now that a reply has been sent
		if pendingFn != nil {
			log.Debug("Invoking pending work")
			go pendingFn()
			pendingFn = nil
		}
	}
}
예제 #4
0
파일: server_test.go 프로젝트: kjplatz/vic
func TestAttachSshSession(t *testing.T) {
	log.SetLevel(log.InfoLevel)

	s := NewAttachServer("", -1)
	assert.NoError(t, s.Start())
	defer s.Stop()

	expectedID := "foo"

	// This should block until the ssh server returns its container ID
	wg := sync.WaitGroup{}
	go func() {
		wg.Add(1)
		defer wg.Done()
		_, err := s.connServer.Get(context.Background(), expectedID, 5*time.Second)
		if !assert.NoError(t, err) {
			return
		}
	}()

	// Dial the attach server.  This is a TCP client
	networkClientCon, err := net.Dial("tcp", s.l.Addr().String())
	if !assert.NoError(t, err) {
		return
	}

	if !assert.NoError(t, serial.HandshakeServer(context.Background(), networkClientCon)) {
		return
	}

	containerConfig := &ssh.ServerConfig{
		NoClientAuth: true,
	}

	signer, err := ssh.ParsePrivateKey(testdata.PEMBytes["dsa"])
	if !assert.NoError(t, err) {
		return
	}
	containerConfig.AddHostKey(signer)

	// create the SSH server on the client.  The attach server will ssh connect to this.
	sshConn, chans, reqs, err := ssh.NewServerConn(networkClientCon, containerConfig)
	if !assert.NoError(t, err) {
		return
	}
	defer sshConn.Close()

	// Service the incoming Channel channel.
	go func() {
		wg.Add(1)
		defer wg.Done()
		for req := range reqs {
			if req.Type == msgs.ContainersReq {
				msg := msgs.ContainersMsg{IDs: []string{expectedID}}
				req.Reply(true, msg.Marshal())
				break
			}
		}
	}()

	go func() {
		wg.Add(1)
		defer wg.Done()
		for ch := range chans {
			assert.Equal(t, ch.ChannelType(), attachChannelType)
			_, _, _ = ch.Accept()
			break
		}
	}()

	wg.Wait()
}