working on setting up remotes

This commit is contained in:
sawka 2022-09-13 17:11:36 -07:00
parent 6f71866663
commit a74ee69da5
6 changed files with 123 additions and 53 deletions

View File

@ -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 (

View File

@ -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,

View File

@ -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
}

View File

@ -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" {

View File

@ -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

View File

@ -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
}