mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
working on setting up remotes
This commit is contained in:
parent
6f71866663
commit
a74ee69da5
@ -86,7 +86,8 @@ CREATE TABLE remote (
|
||||
initpk json NOT NULL,
|
||||
sshopts json NOT NULL,
|
||||
remoteopts json NOT NULL,
|
||||
lastconnectts bigint NOT NULL
|
||||
lastconnectts bigint NOT NULL,
|
||||
archived boolean NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE cmd (
|
||||
|
@ -81,7 +81,8 @@ CREATE TABLE remote (
|
||||
initpk json NOT NULL,
|
||||
sshopts json NOT NULL,
|
||||
remoteopts json NOT NULL,
|
||||
lastconnectts bigint NOT NULL
|
||||
lastconnectts bigint NOT NULL,
|
||||
archived boolean NOT NULL
|
||||
);
|
||||
CREATE TABLE cmd (
|
||||
sessionid varchar(36) NOT NULL,
|
||||
|
@ -461,7 +461,7 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
return nil, fmt.Errorf("invalid alias format")
|
||||
}
|
||||
}
|
||||
connectMode := sstore.ConnectModeStartup
|
||||
connectMode := sstore.ConnectModeAuto
|
||||
if pk.Kwargs["connectmode"] != "" {
|
||||
connectMode = pk.Kwargs["connectmode"]
|
||||
}
|
||||
@ -520,7 +520,7 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
SSHOpts: sshOpts,
|
||||
RemoteOpts: remoteOpts,
|
||||
}
|
||||
err := sstore.InsertRemote(ctx, r)
|
||||
err := remote.AddRemote(ctx, r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create remote %q: %v", r.RemoteCanonicalName, err)
|
||||
}
|
||||
@ -554,11 +554,14 @@ func RemoteShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "physicalid", state.PhysicalId))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "alias", state.RemoteAlias))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "canonicalname", state.RemoteCanonicalName))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "status", state.Status))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "connectmode", state.ConnectMode))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "status", state.Status))
|
||||
if ids.Remote.RemoteState != nil {
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "cwd", ids.Remote.RemoteState.Cwd))
|
||||
}
|
||||
if state.ErrorStr != "" {
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "error", state.ErrorStr))
|
||||
}
|
||||
return sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("show remote [%s] info", ids.Remote.DisplayName),
|
||||
@ -592,6 +595,10 @@ func RemoteArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = remote.ArchiveRemote(ctx, ids.Remote.RemotePtr.RemoteId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("archiving remote: %v", err)
|
||||
}
|
||||
update := sstore.InfoMsgUpdate("remote [%s] archived", ids.Remote.DisplayName)
|
||||
return update, nil
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ type RemoteRuntimeState struct {
|
||||
ErrorStr string `json:"errorstr,omitempty"`
|
||||
DefaultState *sstore.RemoteState `json:"defaultstate"`
|
||||
ConnectMode string `json:"connectmode"`
|
||||
Archived bool `json:"archived"`
|
||||
}
|
||||
|
||||
func logf(rem *sstore.RemoteType, fmtStr string, args ...interface{}) {
|
||||
@ -165,6 +166,59 @@ func LoadRemoteById(ctx context.Context, remoteId string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func AddRemote(ctx context.Context, r *sstore.RemoteType) error {
|
||||
GlobalStore.Lock.Lock()
|
||||
defer GlobalStore.Lock.Unlock()
|
||||
|
||||
existingRemote := getRemoteByCanonicalName_nolock(r.RemoteCanonicalName)
|
||||
if existingRemote != nil {
|
||||
erCopy := existingRemote.getRemoteCopy()
|
||||
if !erCopy.Archived {
|
||||
return fmt.Errorf("duplicate canonical name %q: cannot create new remote", r.RemoteCanonicalName)
|
||||
}
|
||||
r.RemoteId = erCopy.RemoteId
|
||||
}
|
||||
err := sstore.UpsertRemote(ctx, r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create remote %q: %v", r.RemoteCanonicalName, err)
|
||||
}
|
||||
newMsh := MakeMShell(r)
|
||||
GlobalStore.Map[r.RemoteId] = newMsh
|
||||
go newMsh.NotifyRemoteUpdate()
|
||||
if r.ConnectMode == sstore.ConnectModeStartup {
|
||||
go newMsh.Launch()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ArchiveRemote(ctx context.Context, remoteId string) error {
|
||||
GlobalStore.Lock.Lock()
|
||||
defer GlobalStore.Lock.Unlock()
|
||||
msh := GlobalStore.Map[remoteId]
|
||||
if msh == nil {
|
||||
return fmt.Errorf("remote not found, cannot archive")
|
||||
}
|
||||
if msh.Status == StatusConnected {
|
||||
return fmt.Errorf("cannot archive connected remote")
|
||||
}
|
||||
rcopy := msh.getRemoteCopy()
|
||||
archivedRemote := &sstore.RemoteType{
|
||||
RemoteId: rcopy.RemoteId,
|
||||
RemoteType: rcopy.RemoteType,
|
||||
RemoteCanonicalName: rcopy.RemoteCanonicalName,
|
||||
ConnectMode: sstore.ConnectModeManual,
|
||||
Archived: true,
|
||||
}
|
||||
err := sstore.UpsertRemote(ctx, archivedRemote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newMsh := MakeMShell(archivedRemote)
|
||||
GlobalStore.Map[remoteId] = newMsh
|
||||
go newMsh.NotifyRemoteUpdate()
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetRemoteByName(name string) *MShellProc {
|
||||
GlobalStore.Lock.Lock()
|
||||
defer GlobalStore.Lock.Unlock()
|
||||
@ -176,6 +230,16 @@ func GetRemoteByName(name string) *MShellProc {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRemoteByCanonicalName_nolock(name string) *MShellProc {
|
||||
for _, msh := range GlobalStore.Map {
|
||||
rcopy := msh.getRemoteCopy()
|
||||
if rcopy.RemoteCanonicalName == name {
|
||||
return msh
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetRemoteById(remoteId string) *MShellProc {
|
||||
GlobalStore.Lock.Lock()
|
||||
defer GlobalStore.Lock.Unlock()
|
||||
@ -259,6 +323,7 @@ func (msh *MShellProc) GetRemoteRuntimeState() RemoteRuntimeState {
|
||||
PhysicalId: msh.Remote.PhysicalId,
|
||||
Status: msh.Status,
|
||||
ConnectMode: msh.Remote.ConnectMode,
|
||||
Archived: msh.Remote.Archived,
|
||||
}
|
||||
if msh.Err != nil {
|
||||
state.ErrorStr = msh.Err.Error()
|
||||
@ -402,7 +467,9 @@ func (msh *MShellProc) GetNumRunningCommands() int {
|
||||
func (msh *MShellProc) Disconnect() {
|
||||
msh.Lock.Lock()
|
||||
defer msh.Lock.Unlock()
|
||||
msh.ServerProc.Close()
|
||||
if msh.ServerProc != nil {
|
||||
msh.ServerProc.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (msh *MShellProc) GetRemoteName() string {
|
||||
@ -413,12 +480,15 @@ func (msh *MShellProc) GetRemoteName() string {
|
||||
|
||||
func (msh *MShellProc) Launch() {
|
||||
remoteCopy := msh.getRemoteCopy()
|
||||
if remoteCopy.ConnectMode == sstore.ConnectModeArchive {
|
||||
remoteName := remoteCopy.GetName()
|
||||
if remoteCopy.Archived {
|
||||
logf(&remoteCopy, "cannot launch archived remote")
|
||||
return
|
||||
}
|
||||
logf(&remoteCopy, "starting launch")
|
||||
ecmd := convertSSHOpts(remoteCopy.SSHOpts).MakeSSHExecCmd(MShellServerCommand)
|
||||
sshOpts := convertSSHOpts(remoteCopy.SSHOpts)
|
||||
sshOpts.SSHErrorsToTty = true
|
||||
ecmd := sshOpts.MakeSSHExecCmd(MShellServerCommand)
|
||||
cmdPty, err := msh.addControllingTty(ecmd)
|
||||
if err != nil {
|
||||
statusErr := fmt.Errorf("cannot attach controlling tty to mshell command: %w", err)
|
||||
@ -431,7 +501,6 @@ func (msh *MShellProc) Launch() {
|
||||
ecmd.ExtraFiles[len(ecmd.ExtraFiles)-1].Close()
|
||||
}
|
||||
}()
|
||||
remoteName := remoteCopy.GetName()
|
||||
go func() {
|
||||
buf := make([]byte, 100)
|
||||
for {
|
||||
@ -444,9 +513,7 @@ func (msh *MShellProc) Launch() {
|
||||
break
|
||||
}
|
||||
readStr := string(buf[0:n])
|
||||
readStr = strings.ReplaceAll(readStr, "\r", "")
|
||||
readStr = strings.ReplaceAll(readStr, "\n", "\\n")
|
||||
fmt.Printf("[c-pty %s] %d '%s'\n", remoteName, n, readStr)
|
||||
fmt.Printf("[c-pty %s] %d %q\n", remoteName, n, readStr)
|
||||
}
|
||||
}()
|
||||
if remoteName == "test2" {
|
||||
|
@ -71,6 +71,20 @@ func GetRemoteById(ctx context.Context, remoteId string) (*RemoteType, error) {
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
func GetRemoteByCanonicalName(ctx context.Context, cname string) (*RemoteType, error) {
|
||||
var remote *RemoteType
|
||||
err := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `SELECT * FROM remote WHERE remotecanonicalname = ?`
|
||||
m := tx.GetMap(query, cname)
|
||||
remote = RemoteFromMap(m)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
func GetRemoteByPhysicalId(ctx context.Context, physicalId string) (*RemoteType, error) {
|
||||
var remote *RemoteType
|
||||
err := WithTx(ctx, func(tx *TxWrap) error {
|
||||
@ -85,51 +99,32 @@ func GetRemoteByPhysicalId(ctx context.Context, physicalId string) (*RemoteType,
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
func InsertRemote(ctx context.Context, remote *RemoteType) error {
|
||||
if remote == nil {
|
||||
func UpsertRemote(ctx context.Context, r *RemoteType) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("cannot insert nil remote")
|
||||
}
|
||||
if remote.RemoteId == "" {
|
||||
if r.RemoteId == "" {
|
||||
return fmt.Errorf("cannot insert remote without id")
|
||||
}
|
||||
if remote.RemoteCanonicalName == "" {
|
||||
if r.RemoteCanonicalName == "" {
|
||||
return fmt.Errorf("cannot insert remote with canonicalname")
|
||||
}
|
||||
if remote.RemoteType == "" {
|
||||
if r.RemoteType == "" {
|
||||
return fmt.Errorf("cannot insert remote without type")
|
||||
}
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `SELECT remoteid FROM remote WHERE remoteid = ?`
|
||||
if tx.Exists(query, remote.RemoteId) {
|
||||
return fmt.Errorf("duplicate remoteid, cannot create")
|
||||
if tx.Exists(query, r.RemoteId) {
|
||||
tx.ExecWrap(`DELETE FROM remote WHERE remoteid = ?`, r.RemoteId)
|
||||
}
|
||||
if remote.RemoteAlias != "" {
|
||||
query = `SELECT remoteid FROM remote WHERE alias = ?`
|
||||
if tx.Exists(query, remote.RemoteAlias) {
|
||||
return fmt.Errorf("remote has duplicate alias '%s', cannot create", remote.RemoteAlias)
|
||||
}
|
||||
}
|
||||
query = `SELECT remoteid FROM remote WHERE remotecanonicaname = ?`
|
||||
if tx.Exists(query, remote.RemoteCanonicalName) {
|
||||
return fmt.Errorf("remote has duplicate canonicalname '%s', cannot create", remote.RemoteCanonicalName)
|
||||
query = `SELECT remoteid FROM remote WHERE remotecanonicalname = ?`
|
||||
if tx.Exists(query, r.RemoteCanonicalName) {
|
||||
return fmt.Errorf("remote has duplicate canonicalname '%s', cannot create", r.RemoteCanonicalName)
|
||||
}
|
||||
query = `INSERT INTO remote
|
||||
( remoteid, physicalid, remotetype, remotealias, remotecanonicalname, remotesudo, remoteuser, remotehost, connectmode, initpk, sshopts, remoteopts, lastconnectts) VALUES
|
||||
(:remoteid,:physicalid,:remotetype,:remotealias,:remotecanonicalname,:remotesudo,:remoteuser,:remotehost,:connectmode,:initpk,:sshopts,:remoteopts,:lastconnectts)`
|
||||
tx.NamedExecWrap(query, remote.ToMap())
|
||||
return nil
|
||||
})
|
||||
return txErr
|
||||
}
|
||||
|
||||
func ArchiveRemote(ctx context.Context, remoteId string) error {
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `SELECT remoteid FROM remote WHERE remoteid = ?`
|
||||
if !tx.Exists(query, remoteId) {
|
||||
return fmt.Errorf("cannot archive, remote does not exist")
|
||||
}
|
||||
query = `UPDATE remote SET connectmode = ?, physicalid = '', remotetype = '', remotealias = '', initpk = '', sshopts = '', remoteopts = '', lastconnectts = 0 WHERE remoteid = ?`
|
||||
tx.ExecWrap(query, ConnectModeArchive, remoteId)
|
||||
( remoteid, physicalid, remotetype, remotealias, remotecanonicalname, remotesudo, remoteuser, remotehost, connectmode, initpk, sshopts, remoteopts, lastconnectts, archived) VALUES
|
||||
(:remoteid,:physicalid,:remotetype,:remotealias,:remotecanonicalname,:remotesudo,:remoteuser,:remotehost,:connectmode,:initpk,:sshopts,:remoteopts,:lastconnectts,:archived)`
|
||||
tx.NamedExecWrap(query, r.ToMap())
|
||||
return nil
|
||||
})
|
||||
return txErr
|
||||
|
@ -55,7 +55,6 @@ const (
|
||||
ConnectModeStartup = "startup"
|
||||
ConnectModeAuto = "auto"
|
||||
ConnectModeManual = "manual"
|
||||
ConnectModeArchive = "archive"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -72,7 +71,7 @@ func GetSessionDBName() string {
|
||||
}
|
||||
|
||||
func IsValidConnectMode(mode string) bool {
|
||||
return mode == ConnectModeStartup || mode == ConnectModeAuto || mode == ConnectModeManual || mode == ConnectModeArchive
|
||||
return mode == ConnectModeStartup || mode == ConnectModeAuto || mode == ConnectModeManual
|
||||
}
|
||||
|
||||
func GetDB(ctx context.Context) (*sqlx.DB, error) {
|
||||
@ -431,16 +430,14 @@ type RemoteType struct {
|
||||
SSHOpts *SSHOpts `json:"sshopts"`
|
||||
RemoteOpts *RemoteOptsType `json:"remoteopts"`
|
||||
LastConnectTs int64 `json:"lastconnectts"`
|
||||
Archived bool `json:"archived"`
|
||||
}
|
||||
|
||||
func (r *RemoteType) GetName() string {
|
||||
if r.RemoteAlias != "" {
|
||||
return r.RemoteAlias
|
||||
}
|
||||
if r.RemoteUser == "" {
|
||||
return r.RemoteHost
|
||||
}
|
||||
return fmt.Sprintf("%s@%s", r.RemoteUser, r.RemoteHost)
|
||||
return r.RemoteCanonicalName
|
||||
}
|
||||
|
||||
type CmdType struct {
|
||||
@ -473,6 +470,7 @@ func (r *RemoteType) ToMap() map[string]interface{} {
|
||||
rtn["sshopts"] = quickJson(r.SSHOpts)
|
||||
rtn["remoteopts"] = quickJson(r.RemoteOpts)
|
||||
rtn["lastconnectts"] = r.LastConnectTs
|
||||
rtn["archived"] = r.Archived
|
||||
return rtn
|
||||
}
|
||||
|
||||
@ -494,6 +492,7 @@ func RemoteFromMap(m map[string]interface{}) *RemoteType {
|
||||
quickSetJson(&r.SSHOpts, m, "sshopts")
|
||||
quickSetJson(&r.RemoteOpts, m, "remoteopts")
|
||||
quickSetInt64(&r.LastConnectTs, m, "lastconnectts")
|
||||
quickSetBool(&r.Archived, m, "archived")
|
||||
return &r
|
||||
}
|
||||
|
||||
@ -611,7 +610,7 @@ func EnsureLocalRemote(ctx context.Context) error {
|
||||
ConnectMode: ConnectModeStartup,
|
||||
SSHOpts: &SSHOpts{Local: true},
|
||||
}
|
||||
err = InsertRemote(ctx, localRemote)
|
||||
err = UpsertRemote(ctx, localRemote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -643,7 +642,7 @@ func AddTest01Remote(ctx context.Context) error {
|
||||
},
|
||||
ConnectMode: ConnectModeStartup,
|
||||
}
|
||||
err = InsertRemote(ctx, testRemote)
|
||||
err = UpsertRemote(ctx, testRemote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -674,7 +673,7 @@ func AddTest02Remote(ctx context.Context) error {
|
||||
},
|
||||
ConnectMode: ConnectModeStartup,
|
||||
}
|
||||
err = InsertRemote(ctx, testRemote)
|
||||
err = UpsertRemote(ctx, testRemote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user