Skip to content

Commit e3a0f47

Browse files
committed
Mounts are cleanly unmounted on stop and refreshed on start + Standardized
1 parent bdbe143 commit e3a0f47

File tree

8 files changed

+138
-21
lines changed

8 files changed

+138
-21
lines changed

bin/mount.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const p = require('path')
22
const request = require('request-promise-native')
33
const chalk = require('chalk')
44

5-
const { loadMetadata, createMetadata } = require('../lib/metadata')
5+
const { loadMetadata } = require('../lib/metadata')
66

77
exports.command = 'mount <mnt> [key]'
88
exports.desc = 'Mount a hyperdrive at the specified mountpoint.'
@@ -34,7 +34,7 @@ exports.handler = async function (argv) {
3434
bearer: metadata.token
3535
},
3636
body,
37-
resolveWithFullResponse: true,
37+
resolveWithFullResponse: true
3838
})
3939
if (rsp.statusCode === 201) {
4040
let { key, mnt } = rsp.body
@@ -46,4 +46,3 @@ exports.handler = async function (argv) {
4646
console.error(chalk.red(`Could not mount hyperdrive: ${err}`))
4747
}
4848
}
49-

bin/start.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const p = require('path')
22
const { URL } = require('url')
33
const request = require('request-promise-native')
44
const chalk = require('chalk')
5-
const { Monitor } = require('forever-monitor')
65
const forever = require('forever')
76

87
const { loadMetadata, createMetadata } = require('../lib/metadata')
@@ -42,6 +41,7 @@ async function start (argv) {
4241
let endpoint = `http://localhost:${argv.port}`
4342
await createMetadata(endpoint)
4443
forever.startDaemon(p.join(__dirname, '..', 'index.js'), {
44+
uid: 'hypermount',
4545
max: 1,
4646
logFile: './hypermount.log',
4747
outFile: './hypermount.log',

bin/status.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const request = require('request-promise-native')
22
const chalk = require('chalk')
33

4-
const { loadMetadata, createMetadata } = require('../lib/metadata')
4+
const { loadMetadata } = require('../lib/metadata')
55

66
exports.command = 'status'
77
exports.desc = 'Get information about the hypermount daemon.'
@@ -23,4 +23,3 @@ exports.handler = async function (argv) {
2323
console.error(chalk.red(`Could not get server status: ${err}`))
2424
}
2525
}
26-

bin/stop.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
1+
const { URL } = require('url')
2+
const request = require('request-promise-native')
3+
const chalk = require('chalk')
4+
5+
const { loadMetadata } = require('../lib/metadata')
6+
17
exports.command = 'stop'
28
exports.desc = 'Stop the Hypermount daemon.'
3-
exports.handler = function (argv) {
4-
console.log('stop called for args', argv)
9+
exports.handler = async function (argv) {
10+
let metadata = await loadMetadata()
11+
if (metadata) {
12+
try {
13+
await request.post(new URL('/close', metadata.endpoint).toString(), {
14+
auth: {
15+
bearer: metadata.token
16+
}
17+
})
18+
console.log(chalk.green(`The Hypermount daemon has been stopped.`))
19+
} catch (err) {
20+
console.log('err:', err)
21+
console.error(chalk.red(`Could not stop the daemon.`))
22+
}
23+
}
524
}
6-

bin/unmount.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const p = require('path')
22
const request = require('request-promise-native')
33
const chalk = require('chalk')
44

5-
const { loadMetadata, createMetadata } = require('../lib/metadata')
5+
const { loadMetadata } = require('../lib/metadata')
66

77
exports.command = 'unmount <mnt>'
88
exports.desc = 'Unmount the hyperdrive that was mounted at the specified mountpoint.'
@@ -19,7 +19,7 @@ exports.handler = async function (argv) {
1919
bearer: metadata.token
2020
},
2121
body,
22-
resolveWithFullResponse: true,
22+
resolveWithFullResponse: true
2323
})
2424
if (rsp.statusCode === 200) {
2525
console.log(chalk.green(`Unmounted hyperdrive at ${argv.mnt}`))

cli.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
#!/usr/bin/env node
2-
3-
const datEncoding = require('dat-encoding')
4-
const forever = require('forever-monitor')
52
const yargs = require('yargs')
63

74
yargs.commandDir('bin')

index.js

Lines changed: 109 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1-
const datEncoding = require('dat-encoding')
1+
const p = require('path')
2+
23
const corestore = require('corestore')
34
const hyperdrive = require('hyperdrive')
45
const hyperfuse = require('hyperdrive-fuse')
56
const express = require('express')
67
const level = require('level')
8+
const through = require('through2')
9+
const pump = require('pump')
10+
const mkdirp = require('mkdirp')
711
const argv = require('yargs').argv
812

913
const { loadMetadata } = require('./lib/metadata')
1014

15+
const Status = {
16+
UNMOUNTED: 0,
17+
MOUNTED: 1
18+
}
19+
1120
class Hypermount {
1221
constructor (store) {
1322
this.store = store
@@ -28,11 +37,11 @@ class Hypermount {
2837
sparseMetadata: (opts.sparseMetadata !== undefined) ? opts.sparseMetadata : true
2938
})
3039

31-
return hyperfuse.mount(drive, mnt)
40+
return hyperfuse.mount(drive, mnt)
3241
}
3342

3443
unmount (mnt) {
35-
return hyperfuse.unmount(mnt)
44+
return hyperfuse.unmount(mnt)
3645
}
3746

3847
close () {
@@ -42,11 +51,25 @@ class Hypermount {
4251

4352
async function start () {
4453
const metadata = await loadMetadata()
45-
const store = corestore(argv.storage || './storage', {
54+
const storageRoot = argv.storage || './storage'
55+
56+
await (() => {
57+
return new Promise((resolve, reject) => {
58+
mkdirp(storageRoot, err => {
59+
if (err) return reject(err)
60+
return resolve()
61+
})
62+
})
63+
})()
64+
65+
const store = corestore(p.join(storageRoot, 'cores'), {
4666
network: {
4767
port: argv.replicationPort || 3006
4868
}
4969
})
70+
const db = level(p.join(storageRoot, 'db'), {
71+
valueEncoding: 'json'
72+
})
5073
const hypermount = new Hypermount(store)
5174
const app = express()
5275

@@ -60,40 +83,119 @@ async function start () {
6083
app.post('/mount', async (req, res) => {
6184
try {
6285
console.log('req.body:', req.body)
63-
let { key, mnt } = await hypermount.mount(req.body.key, req.body.mnt, req.body)
86+
let { key, mnt } = req.body
87+
key = await mount(hypermount, db, key, mnt, req.body)
6488
return res.status(201).json({ key, mnt })
6589
} catch (err) {
6690
console.error('Mount error:', err)
6791
return res.sendStatus(500)
6892
}
6993
})
94+
7095
app.post('/unmount', async (req, res) => {
7196
try {
72-
await hypermount.unmount(req.body.mnt)
97+
const mnt = req.body.mnt
98+
await unmount(hypermount, db, mnt)
99+
73100
return res.sendStatus(200)
74101
} catch (err) {
75102
console.error('Unmount error:', err)
76103
return res.sendStatus(500)
77104
}
78105
})
106+
79107
app.post('/close', async (req, res) => {
80108
try {
109+
await unmountAll(hypermount, db)
110+
console.log('unmounted them all')
81111
await store.close()
112+
await db.close()
82113
server.close()
83-
return res.sendStatus(200)
114+
115+
res.sendStatus(200)
84116
} catch (err) {
85117
console.error('Close error:', err)
86118
return res.sendStatus(500)
87119
}
88120
})
121+
89122
app.get('/status', async (req, res) => {
90123
return res.sendStatus(200)
91124
})
92125

93126
await store.ready()
127+
await refreshMounts(hypermount, db)
128+
94129
var server = app.listen(argv.port || 3005)
95130
}
96131

132+
async function mount (hypermount, db, key, mnt, opts) {
133+
let { key: mountedKey } = await hypermount.mount(key, mnt, opts)
134+
135+
await db.put(mnt, {
136+
...opts,
137+
key: mountedKey,
138+
mnt,
139+
status: Status.MOUNTED
140+
})
141+
142+
return mountedKey
143+
}
144+
145+
async function unmount (hypermount, db, mnt) {
146+
await hypermount.unmount(mnt)
147+
148+
let record = await db.get(mnt)
149+
if (!record) return
150+
record.status = Status.UNMOUNTED
151+
152+
await db.put(mnt, record)
153+
}
154+
155+
function unmountAll (hypermount, db) {
156+
return new Promise((resolve, reject) => {
157+
pump(
158+
db.createReadStream(),
159+
through.obj(({ key, value: record }, enc, cb) => {
160+
if (record.status === Status.MOUNTED) {
161+
console.log('UNMOUNTING in unmountAll:', key)
162+
let unmountPromise = unmount(hypermount, db, key)
163+
unmountPromise.then(() => cb(null))
164+
unmountPromise.catch(err => cb(err))
165+
} else {
166+
return cb(null)
167+
}
168+
}),
169+
err => {
170+
if (err) return reject(err)
171+
return resolve()
172+
}
173+
)
174+
})
175+
}
176+
177+
function refreshMounts (hypermount, db) {
178+
return new Promise((resolve, reject) => {
179+
pump(
180+
db.createReadStream(),
181+
through.obj(({ key, value: record }, enc, cb) => {
182+
if (record.status === Status.UNMOUNTED) {
183+
console.log(`Refreshing mount for ${JSON.stringify(record)}`)
184+
const mountPromise = mount(hypermount, db, record.key, key, record)
185+
mountPromise.then(() => cb(null))
186+
mountPromise.catch(cb)
187+
} else {
188+
return cb(null)
189+
}
190+
}),
191+
err => {
192+
if (err) return reject(err)
193+
return resolve()
194+
}
195+
)
196+
})
197+
}
198+
97199
if (require.main === module) {
98200
start()
99201
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@
3535
"hyperdrive": "git+https://github.com/mafintosh/hyperdrive.git#v10",
3636
"hyperdrive-fuse": "git+https://github.com/andrewosh/hyperdrive-fuse",
3737
"level": "^4.0.0",
38+
"mkdirp": "^0.5.1",
3839
"request": "^2.88.0",
3940
"request-promise-native": "^1.0.7",
4041
"sodium-universal": "^2.0.0",
42+
"through2": "^3.0.1",
4143
"yargs": "^13.2.1"
4244
},
4345
"devDependencies": {

0 commit comments

Comments
 (0)