Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1aab0cf4a5 |
@@ -265,6 +265,10 @@ It refreshes over the connections that are already open. `^r` logs in again,
|
||||
which is how a session that has died is recovered; doing that every ten seconds
|
||||
would be three logins a minute for nothing.
|
||||
|
||||
`^l` is not the only way in: making a machine from a template turns it on, since
|
||||
a clone that has just been started is exactly the screen this is for, and says
|
||||
so in the same line that reports the machine.
|
||||
|
||||
Two things come with it.
|
||||
|
||||
**The line under the table says what just changed.** A table shows what is; this
|
||||
@@ -479,10 +483,17 @@ puts it somewhere other than the template's own.
|
||||
**It does not wait.** A clone copies every disk the template has, which is
|
||||
minutes to the half hour, and a list frozen for that long is a list nobody would
|
||||
start one from. The task hangs off the template in vCenter, so the row it was
|
||||
started from shows how far along it is in its TASK column — `^l` makes that move
|
||||
on its own, and announces the new machine on the line under the table when it
|
||||
exists. `gvm new` on the command line does wait: a script that gets its prompt
|
||||
back wants the machine to be there.
|
||||
started from shows how far along it is in its TASK column. `gvm new` on the
|
||||
command line does wait: a script that gets its prompt back wants the machine to
|
||||
be there.
|
||||
|
||||
**And it goes to that column.** The machine's sheet — which is where the menu
|
||||
was opened and a page of facts about the *template* — is put away, the list
|
||||
comes back with the cursor still on the row the clone hangs off, and live mode
|
||||
turns itself on if it was off, so the percentage moves on its own and the line
|
||||
under the table announces the new machine when it exists. `^l` ends it again.
|
||||
Naming the key that would make an invisible figure move is three steps of
|
||||
housekeeping after the one decision that mattered.
|
||||
|
||||
The rest of a template's menu is greyed out with "a template" next to it, because
|
||||
vSphere will not start one, snapshot one or reconfigure one. They are greyed
|
||||
@@ -586,7 +597,8 @@ answer short of the same answer.
|
||||
the line that is left on the screen afterwards — this is a number somebody
|
||||
writes down:
|
||||
|
||||
web05 is being made at 141.14.140.182 — ubuntu-tpl shows how far along it is
|
||||
web05 is being made at 141.14.140.182 — live on, ubuntu-tpl shows how far
|
||||
along it is
|
||||
|
||||
Three more things about it are deliberate:
|
||||
|
||||
|
||||
+26
-3
@@ -594,8 +594,14 @@ func sizePrompt(r vmRow, sz sizing, k sizeKind) string {
|
||||
// minutes to the half hour, and a list that is frozen for that long is a list
|
||||
// nobody will start one from. vCenter carries the task either way, and it hangs
|
||||
// off the template — so the row this was started from shows how far along it is
|
||||
// in its TASK column, and ^l makes that move on its own. The machine itself
|
||||
// turns up in the list when it exists, which live mode announces.
|
||||
// in its TASK column. The machine itself turns up in the list when it exists,
|
||||
// which live mode announces.
|
||||
//
|
||||
// Which is why the end of it is a screen and not only a sentence: the sheet
|
||||
// goes away, the list comes back with the cursor still on the template, and
|
||||
// live mode turns itself on. Telling somebody that a figure they cannot see
|
||||
// exists, and which key would make it move, is three steps of housekeeping
|
||||
// after the one decision that mattered.
|
||||
//
|
||||
// The question at the end is the plain one. Nothing is lost here; something is
|
||||
// made, and what has to be read before it is made is *where* — which is why
|
||||
@@ -795,13 +801,30 @@ func (b *browser) deployAsk(r vmRow, src deploySource, t deployTarget, name stri
|
||||
b.setStatus(colErr, err.Error())
|
||||
return
|
||||
}
|
||||
// And then the screen it can be watched on. This was started from the
|
||||
// template's sheet — a page of facts about the machine being copied, which
|
||||
// is not what anybody is here for now. The list is: the clone's progress
|
||||
// stands in the TASK column of the row the cursor is already on, the new
|
||||
// machine turns up there when it exists, and the line under the table says
|
||||
// so. Live mode goes with it, or the percentage would sit where it was
|
||||
// until somebody pressed a key.
|
||||
//
|
||||
// Decided before done, which is what puts the task on the row, and applied
|
||||
// after it, so that the interval it schedules is the busy one.
|
||||
watching := ""
|
||||
if !b.live {
|
||||
watching = "live on, "
|
||||
}
|
||||
b.closeDetail()
|
||||
|
||||
// The address is in the line that survives, not only in the question that
|
||||
// was answered a moment ago: it is the one thing here somebody writes down.
|
||||
at := ""
|
||||
if opts.ip != "" && opts.customising() {
|
||||
at = " at " + opts.ip
|
||||
}
|
||||
b.done(SF("%s is being made%s — %s shows how far along it is", name, at, src.name))
|
||||
b.done(SF("%s is being made%s — %s%s shows how far along it is", name, at, watching, src.name))
|
||||
b.watchLive()
|
||||
}
|
||||
|
||||
// working puts a line on the screen before an operation that will block the loop
|
||||
|
||||
@@ -1012,13 +1012,7 @@ func (b *browser) detailKey(k key) {
|
||||
|
||||
switch k.special {
|
||||
case keyEsc, keyEnter, keyBackspace, keyLeft:
|
||||
b.detail, b.dscroll = nil, 0
|
||||
// The events go with the visit, not with the machine: coming back to a
|
||||
// sheet half an hour later and finding half-hour-old events under a
|
||||
// label that says nothing about when they were read would be the one
|
||||
// stale thing on an otherwise freshly read screen. They are one
|
||||
// keystroke away again.
|
||||
b.events, b.eventsOf = nil, ""
|
||||
b.closeDetail()
|
||||
b.setStatus("", "")
|
||||
case keyCtrlA:
|
||||
b.openMenu()
|
||||
@@ -1717,6 +1711,19 @@ func (b *browser) openDetail() {
|
||||
b.dscroll = 0
|
||||
}
|
||||
|
||||
// closeDetail puts the sheet away and leaves the list underneath it. It is what
|
||||
// Esc does, and also what an action does when what happens next is to be
|
||||
// watched in the table rather than read on one machine's page (actions.go).
|
||||
//
|
||||
// The events go with the visit, not with the machine: coming back to a sheet
|
||||
// half an hour later and finding half-hour-old events under a label that says
|
||||
// nothing about when they were read would be the one stale thing on an
|
||||
// otherwise freshly read screen. They are one keystroke away again.
|
||||
func (b *browser) closeDetail() {
|
||||
b.detail, b.dscroll = nil, 0
|
||||
b.events, b.eventsOf = nil, ""
|
||||
}
|
||||
|
||||
// eventSheet is the history as sheet lines: the label on the first, each line in
|
||||
// the colour of its own severity. It is appended to the sheet rather than built
|
||||
// into vmDetail because vmDetail asks nothing of the network and this is the one
|
||||
|
||||
@@ -380,6 +380,29 @@ func TestTheSheetClosesWhenItsMachineGoes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Closing the sheet leaves nothing of the visit behind. The events are the part
|
||||
// that would keep: they are read once, on request, and a sheet opened again
|
||||
// half an hour later must not show them under a label that says nothing about
|
||||
// when they were read. Esc does this, and so does a deployment, which puts the
|
||||
// sheet away to leave the list watching the clone (actions.go).
|
||||
func TestClosingTheSheetForgetsTheVisit(t *testing.T) {
|
||||
b := testBrowser("ubuntu-tpl", "web01")
|
||||
b.applySort()
|
||||
b.events = []eventLine{{text: "08.09. 11:41 Cannot connect to host esx03", col: colFull}}
|
||||
b.eventsOf = b.current().id()
|
||||
b.openDetail()
|
||||
b.dscroll = 4
|
||||
|
||||
b.closeDetail()
|
||||
|
||||
if b.detail != nil || b.dscroll != 0 {
|
||||
t.Errorf("the sheet is still there: %d lines, scrolled to %d", len(b.detail), b.dscroll)
|
||||
}
|
||||
if b.events != nil || b.eventsOf != "" {
|
||||
t.Errorf("the events of %q were kept: %v", b.eventsOf, b.events)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetailSheetHasTheParameters(t *testing.T) {
|
||||
sheet := sheetText(vmDetail(testRow("web01", true, "10.0.0.5"), []string{"none"}, colOff))
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// Everything else in the interactive half happens because somebody pressed a
|
||||
// key. This is the part that happens because time passed: `^l` turns it on and
|
||||
// the list re-reads itself every few seconds, which turns gvm from something one
|
||||
// looks at into something one leaves open on a second screen.
|
||||
// looks at into something one leaves open on a second screen. Starting a clone
|
||||
// turns it on as well (watchLive), because that is a screen made to be watched
|
||||
// whether or not anybody thought to ask for it first.
|
||||
//
|
||||
// Three things come with it, and they are here rather than in browse.go because
|
||||
// they only mean anything together:
|
||||
@@ -69,6 +71,27 @@ func (b *browser) toggleLive() {
|
||||
b.setStatus(colBusy, "live on — the list re-reads itself; ^l off")
|
||||
}
|
||||
|
||||
// watchLive turns live mode on because something with a figure to watch was
|
||||
// just set going, and reports whether it had to. ^l is somebody asking for a
|
||||
// screen that keeps itself up to date; this is gvm deciding that a clone it has
|
||||
// just started makes the list one of those, since the progress in the TASK
|
||||
// column is the whole reason to still be looking at it. It stays on afterwards,
|
||||
// like the mode it is — ^l ends it, and the title says it is running.
|
||||
//
|
||||
// Unlike toggleLive it does not sweep at once. The caller has just re-read the
|
||||
// row it acted on, so the first tick belongs one interval away rather than now
|
||||
// — and that interval is already the busy one, because that row is the one
|
||||
// carrying the task.
|
||||
func (b *browser) watchLive() bool {
|
||||
if b.live {
|
||||
return false
|
||||
}
|
||||
b.live = true
|
||||
b.liveGap = b.liveInterval()
|
||||
b.liveNext = time.Now().Add(b.liveGap)
|
||||
return true
|
||||
}
|
||||
|
||||
// liveReady reports whether a tick may happen now. Only the list and a
|
||||
// machine's sheet are refreshed underneath somebody: the menu decides what it
|
||||
// offers from the state it was drawn with, the picker holds a list of snapshots
|
||||
|
||||
@@ -485,3 +485,34 @@ func TestToggleLiveSaysSoAndLooksNow(t *testing.T) {
|
||||
t.Errorf("turning it off said %q", b.status)
|
||||
}
|
||||
}
|
||||
|
||||
// A clone that has just been started makes the list a screen worth watching, so
|
||||
// live mode turns itself on rather than leaving a percentage that moves only
|
||||
// when somebody remembers ^l. The first tick is an interval away rather than
|
||||
// now — the action re-read its own row a moment ago — and that interval is the
|
||||
// busy one, because the row it re-read is the one carrying the task.
|
||||
func TestStartingAClonePutsTheListOnWatch(t *testing.T) {
|
||||
b := testBrowser("ubuntu-tpl", "web01")
|
||||
b.rows[0].task = &runningTask{what: "clone", progress: 2}
|
||||
|
||||
if !b.watchLive() {
|
||||
t.Fatal("watchLive did not report that it had to turn live mode on")
|
||||
}
|
||||
if !b.live {
|
||||
t.Fatal("live mode is off after a clone was started")
|
||||
}
|
||||
if d := b.liveIn(); d > liveBusy || d < liveBusy/2 {
|
||||
t.Errorf("the first refresh is %s away, want about %s", d, liveBusy)
|
||||
}
|
||||
|
||||
// Already on is not a reason to touch it: a tick that was due in half a
|
||||
// second must not be pushed back to two because a second clone was started.
|
||||
b.liveNext = time.Now().Add(liveBusy / 4)
|
||||
due := b.liveNext
|
||||
if b.watchLive() {
|
||||
t.Error("watchLive reported turning on a mode that was already on")
|
||||
}
|
||||
if !b.liveNext.Equal(due) {
|
||||
t.Errorf("the pending tick moved from %s to %s", due, b.liveNext)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.3.7
|
||||
1.3.8
|
||||
|
||||
Reference in New Issue
Block a user