Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
nomad-FAIR
Commits
0600823c
Commit
0600823c
authored
Dec 23, 2018
by
Markus Scheidgen
Browse files
Various refactorings and fixes in GUI due to latest API changes.
parent
278fb1f7
Pipeline
#41239
failed with stages
in 17 minutes and 32 seconds
Changes
15
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
gui/package.json
View file @
0600823c
...
...
@@ -24,10 +24,9 @@
"url-parse"
:
"^1.4.3"
},
"scripts"
:
{
"metainfo"
:
"git clone --single-branch -b nomad-fair http://gitlab.mpcdf.mpg.de/nomad-lab/nomad-meta-info.git --depth=1 public/metainfo"
,
"gitinfo"
:
"echo
\"
{
\\\"
log
\\\"
:
\\\"
$(git log -1 --oneline)
\\\"
,
\\\"
ref
\\\"
:
\\\"
$(git describe --all)
\\\"
,
\\\"
version
\\\"
:
\\\"
$(git describe)
\\\"
}
\"
> src/gitinfo.json"
,
"start"
:
"
yarn metainfo;
react-scripts start"
,
"build"
:
"
yarn metainfo;
react-scripts build"
,
"start"
:
"react-scripts start"
,
"build"
:
"react-scripts build"
,
"test"
:
"react-scripts test --env=jsdom"
,
"eject"
:
"react-scripts eject"
},
...
...
gui/src/api.js
View file @
0600823c
import
{
UploadRequest
}
from
'
@navjobs/upload
'
import
Swagger
from
'
swagger-client
'
import
{
apiBase
,
appStaticBase
}
from
'
./config
'
import
{
apiBase
}
from
'
./config
'
const
auth_headers
=
{
Authorization
:
'
Basic
'
+
btoa
(
'
sheldon.cooper@nomad-fairdi.tests.de:password
'
)
...
...
@@ -19,29 +19,31 @@ const swaggerPromise = Swagger(`${apiBase}/swagger.json`, {
})
const
networkError
=
(
e
)
=>
{
console
.
log
(
e
)
throw
Error
(
'
Network related error, cannot reach API:
'
+
e
)
}
const
handleJsonErrors
=
()
=>
{
throw
Error
(
'
Server return unexpected data format.
'
)
const
handleJsonErrors
=
(
e
)
=>
{
console
.
log
(
e
)
throw
Error
(
'
API return unexpected data format.
'
)
}
const
handleResponseErrors
=
(
response
)
=>
{
if
(
!
response
.
ok
)
{
return
response
.
json
()
.
catch
(()
=>
{
throw
Error
(
`API
/object storage
error (
${
response
.
status
}
):
${
response
.
statusText
}
`
)
throw
Error
(
`API error (
${
response
.
status
}
):
${
response
.
statusText
}
`
)
}).
then
(
data
=>
{
throw
Error
(
`API
/object storage
error (
${
response
.
status
}
):
${
data
.
message
}
`
)
throw
Error
(
`API error (
${
response
.
status
}
):
${
data
.
message
}
`
)
})
}
return
response
}
class
Upload
{
constructor
(
json
,
created
)
{
constructor
(
json
)
{
this
.
uploading
=
0
this
.
_assignFromJson
(
json
,
created
)
this
.
_assignFromJson
(
json
)
}
uploadFile
(
file
)
{
...
...
@@ -58,7 +60,6 @@ class Upload {
},
files
:
[
file
],
progress
:
value
=>
{
console
.
log
(
value
)
this
.
uploading
=
value
}
}
...
...
@@ -77,41 +78,39 @@ class Upload {
.
then
(()
=>
this
)
}
_assignFromJson
(
uploadJson
,
created
)
{
_assignFromJson
(
uploadJson
)
{
Object
.
assign
(
this
,
uploadJson
)
if
(
this
.
current_task
!==
this
.
tasks
[
0
])
{
this
.
uploading
=
100
this
.
waiting
=
false
}
else
{
this
.
waiting
=
true
if
(
this
.
calcs
)
{
this
.
calcs
.
results
.
forEach
(
calc
=>
{
const
archiveId
=
calc
.
archive_id
.
split
(
'
/
'
)
calc
.
upload_hash
=
archiveId
[
0
]
calc
.
calc_hash
=
archiveId
[
1
]
})
}
}
get
(
page
,
perPage
,
orderBy
,
order
)
{
if
(
!
page
)
page
=
1
if
(
!
perPage
)
perPage
=
5
if
(
!
orderBy
)
orderBy
=
'
mainfile
'
if
(
!
order
)
order
=
'
desc
'
order
=
order
===
'
desc
'
?
-
1
:
1
if
(
this
.
uploading
!==
null
&&
this
.
uploading
!==
100
)
{
return
new
Promise
(
resolve
=>
resolve
(
this
))
}
else
{
const
qparams
=
`page=
${
page
}
&per_page=
${
perPage
}
&order_by=
${
orderBy
}
&order=
${
order
}
`
return
fetch
(
`
${
apiBase
}
/uploads/
${
this
.
upload_id
}
?
${
qparams
}
`
,
{
method
:
'
GET
'
,
headers
:
auth_headers
})
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
())
.
then
(
uploadJson
=>
{
this
.
_assignFromJson
(
uploadJson
)
return
this
})
if
(
this
.
upload_id
)
{
return
swaggerPromise
.
then
(
client
=>
client
.
apis
.
uploads
.
get_upload
({
upload_id
:
this
.
upload_id
,
page
:
page
||
1
,
per_page
:
perPage
||
5
,
order_by
:
orderBy
||
'
mainfile
'
,
order
:
order
||
-
1
}))
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
body
)
.
then
(
uploadJson
=>
{
this
.
_assignFromJson
(
uploadJson
)
return
this
})
}
else
{
return
new
Promise
(
resolve
=>
resolve
(
this
))
}
}
}
}
...
...
@@ -119,33 +118,43 @@ class Upload {
function
createUpload
(
name
)
{
return
new
Upload
({
name
:
name
,
tasks
:
[
'
UPLOADING
'
],
current_task
:
'
UPLOADING
'
tasks
:
[
'
uploading
'
],
current_task
:
'
uploading
'
,
uploading
:
0
,
create_time
:
new
Date
()
},
true
)
}
function
getUploads
()
{
return
fetch
(
`
${
apiBase
}
/uploads/`
,
{
method
:
'
GET
'
,
headers
:
auth_headers
})
async
function
getUploads
()
{
const
client
=
await
swaggerPromise
return
client
.
apis
.
uploads
.
get_uploads
()
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
())
.
then
(
uploadsJson
=>
uploadsJson
.
map
(
uploadJson
=>
new
Upload
(
uploadJson
)))
.
then
(
response
=>
response
.
body
.
map
(
uploadJson
=>
{
const
upload
=
new
Upload
(
uploadJson
)
upload
.
uploading
=
100
return
upload
}))
}
function
archive
(
uploadHash
,
calcHash
)
{
return
fetch
(
archiveUrl
(
uploadHash
,
calcHash
))
async
function
archive
(
uploadHash
,
calcHash
)
{
const
client
=
await
swaggerPromise
return
client
.
apis
.
archive
.
get_archive_calc
({
upload_hash
:
uploadHash
,
calc_hash
:
calcHash
})
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
()
)
.
then
(
response
=>
response
.
body
)
}
function
calcProcLog
(
archiveId
)
{
return
fetch
(
`
${
apiBase
}
/archive/logs/
${
archiveId
}
`
)
async
function
calcProcLog
(
uploadHash
,
calcHash
)
{
const
client
=
await
swaggerPromise
console
.
log
(
uploadHash
+
calcHash
)
return
client
.
apis
.
archive
.
get_archive_logs
({
upload_hash
:
uploadHash
,
calc_hash
:
calcHash
})
.
catch
(
networkError
)
.
then
(
response
=>
{
if
(
!
response
.
ok
)
{
...
...
@@ -155,62 +164,53 @@ function calcProcLog(archiveId) {
return
handleResponseErrors
(
response
)
}
}
else
{
return
response
.
text
()
return
response
.
text
}
})
}
function
archiveUrl
(
uploadHash
,
calcHash
)
{
return
`
${
apiBase
}
/archive/
${
uploadHash
}
/
${
calcHash
}
`
}
function
repo
(
uploadH
ash
,
calcHash
)
{
return
fetch
(
`
${
apiBase
}
/repo/
${
uploadHash
}
/
${
calcHash
}
`
)
async
function
repo
(
uploadHash
,
calcHash
)
{
const
client
=
await
swaggerPromise
return
client
.
apis
.
repo
.
get_repo_calc
({
upload_hash
:
uploadHash
,
calc_h
ash
:
calcHash
}
)
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
()
)
.
then
(
response
=>
response
.
body
)
}
function
repoAll
(
page
,
perPage
,
owner
)
{
return
fetch
(
`
${
apiBase
}
/repo/?page=
${
page
}
&per_page=
${
perPage
}
&owner=
${
owner
||
'
all
'
}
`
,
{
method
:
'
GET
'
,
head
er
s
:
auth_headers
async
function
repoAll
(
page
,
perPage
,
owner
)
{
const
client
=
await
swaggerPromise
return
client
.
apis
.
repo
.
get_calcs
({
page
:
page
,
per_page
:
perPage
,
ow
er
:
owner
||
'
all
'
})
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
()
)
.
then
(
response
=>
response
.
body
)
}
function
deleteUpload
(
uploadId
)
{
return
fetch
(
`
${
apiBase
}
/uploads/
${
uploadId
}
`
,
{
method
:
'
DELETE
'
,
headers
:
auth_headers
})
async
function
deleteUpload
(
uploadId
)
{
const
client
=
await
swaggerPromise
return
client
.
apis
.
uploads
.
delete_upload
({
upload_id
:
uploadId
})
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
()
)
.
then
(
response
=>
response
.
body
)
}
function
unstageUpload
(
uploadId
)
{
return
fetch
(
`
${
apiBase
}
/uploads/
${
uploadId
}
`
,
{
method
:
'
POST
'
,
body
:
JSON
.
stringify
({
async
function
unstageUpload
(
uploadId
)
{
const
client
=
await
swaggerPromise
return
client
.
apis
.
uploads
.
exec_upload_command
({
upload_id
:
uploadId
,
payload
:
{
operation
:
'
unstage
'
}),
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
...
auth_headers
}
})
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
()
)
.
then
(
response
=>
response
.
body
)
}
let
cachedMetaInfo
=
null
...
...
@@ -220,7 +220,7 @@ async function getMetaInfo() {
return
cachedMetaInfo
}
else
{
const
loadMetaInfo
=
async
(
path
)
=>
{
return
fetch
(
`
${
ap
pStaticBase
}
/metainfo/meta_info/nomad_
meta
_
info/
${
path
}
`
)
return
fetch
(
`
${
ap
iBase
}
/archive/
metainfo/
${
path
}
`
)
.
catch
(
networkError
)
.
then
(
handleResponseErrors
)
.
then
(
response
=>
response
.
json
())
...
...
@@ -262,7 +262,6 @@ const api = {
getUploads
:
getUploads
,
archive
:
archive
,
calcProcLog
:
calcProcLog
,
archiveUrl
:
archiveUrl
,
repo
:
repo
,
repoAll
:
repoAll
,
getMetaInfo
:
getMetaInfo
...
...
gui/src/components/ArchiveCalc.js
View file @
0600823c
...
...
@@ -103,8 +103,7 @@ class ArchiveCalc extends React.Component {
*quantities* by visiting the [meta-info](/metainfo) browser.
The tree below shows all calculation data in nomad's *hierachical* and
*code independent* archive format. You can download it
[here](
${
api
.
archiveUrl
(
uploadHash
,
calcHash
)}
). Click on values to
*code independent* archive format. Click on values to
see a *meta-info* description.
`
}
<
/Markdown
>
<
Typography
className
=
{
classes
.
logLink
}
>
...
...
@@ -124,7 +123,8 @@ class ArchiveCalc extends React.Component {
<
/Paper
>
<
CalcProcLogPopper
open
=
{
this
.
state
.
showLogs
}
archiveId
=
{
`
${
uploadHash
}
/
${
calcHash
}
`
}
uploadHash
=
{
uploadHash
}
calcHash
=
{
calcHash
}
onClose
=
{()
=>
this
.
setState
({
showLogs
:
false
})}
anchorEl
=
{
this
.
logPopperAnchor
.
current
}
raiseError
=
{
this
.
props
.
raiseError
}
...
...
gui/src/components/CalcLinks.js
View file @
0600823c
...
...
@@ -10,7 +10,6 @@ import Link from 'react-router-dom/Link'
class
CalcLink
extends
React
.
Component
{
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
calcId
:
PropTypes
.
string
,
uploadHash
:
PropTypes
.
string
,
calcHash
:
PropTypes
.
string
,
disabled
:
PropTypes
.
bool
...
...
@@ -24,19 +23,18 @@ class CalcLink extends React.Component {
});
render
()
{
const
{
uploadHash
,
calcHash
,
classes
,
calcId
,
disabled
}
=
this
.
props
const
id
=
calcId
||
`
${
uploadHash
}
/
${
calcHash
}
`
const
{
uploadHash
,
calcHash
,
classes
,
disabled
}
=
this
.
props
return
(
<
div
className
=
{
classes
.
root
}
>
<
MuiThemeProvider
theme
=
{
repoTheme
}
>
<
IconButton
color
=
"
primary
"
component
=
{
Link
}
to
=
{
`/repo/
${
id
}
`
}
disabled
=
{
disabled
}
><
RepoIcon
/><
/IconButton
>
<
IconButton
color
=
"
primary
"
component
=
{
Link
}
to
=
{
`/repo/
${
uploadHash
}
/
${
calcHash
}
`
}
disabled
=
{
disabled
}
><
RepoIcon
/><
/IconButton
>
<
/MuiThemeProvider
>
<
MuiThemeProvider
theme
=
{
archiveTheme
}
>
<
IconButton
color
=
"
primary
"
component
=
{
Link
}
to
=
{
`/archive/
${
id
}
`
}
disabled
=
{
disabled
}
><
ArchiveIcon
/><
/IconButton
>
<
IconButton
color
=
"
primary
"
component
=
{
Link
}
to
=
{
`/archive/
${
uploadHash
}
/
${
calcHash
}
`
}
disabled
=
{
disabled
}
><
ArchiveIcon
/><
/IconButton
>
<
/MuiThemeProvider
>
<
MuiThemeProvider
theme
=
{
encTheme
}
>
<
IconButton
color
=
"
primary
"
component
=
{
Link
}
to
=
{
`/enc/
${
id
}
`
}
disabled
=
{
disabled
}
><
EncIcon
/><
/IconButton
>
<
IconButton
color
=
"
primary
"
component
=
{
Link
}
to
=
{
`/enc/
${
uploadHash
}
/
${
calcHash
}
`
}
disabled
=
{
disabled
}
><
EncIcon
/><
/IconButton
>
<
/MuiThemeProvider
>
<
/div
>
)
...
...
gui/src/components/CalcProcLogPopper.js
View file @
0600823c
...
...
@@ -11,7 +11,8 @@ class CalcProcLogPopper extends React.Component {
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
raiseError
:
PropTypes
.
func
.
isRequired
,
archiveId
:
PropTypes
.
string
.
isRequired
,
uploadHash
:
PropTypes
.
string
.
isRequired
,
calcHash
:
PropTypes
.
string
.
isRequired
,
open
:
PropTypes
.
bool
,
onClose
:
PropTypes
.
func
,
anchorEl
:
PropTypes
.
any
...
...
@@ -28,8 +29,8 @@ class CalcProcLogPopper extends React.Component {
}
componentDidMount
()
{
const
{
archiveId
}
=
this
.
props
api
.
calcProcLog
(
archiveId
).
then
(
logs
=>
{
const
{
uploadHash
,
calcHash
}
=
this
.
props
api
.
calcProcLog
(
uploadHash
,
calcHash
).
then
(
logs
=>
{
if
(
logs
&&
logs
!==
''
)
{
this
.
setState
({
logs
:
logs
})
}
...
...
gui/src/components/Upload.js
View file @
0600823c
...
...
@@ -80,7 +80,7 @@ class Upload extends React.Component {
orderBy
:
'
status
'
,
order
:
'
asc
'
},
archiveLogs
:
null
,
//
archive
id of archive to show logs for
archiveLogs
:
null
,
//
{ uploadHash, calcHash }
id
s
of archive to show logs for
loading
:
true
,
// its loading data from the server and the user should know about it
updating
:
true
// it is still not complete and continieusly looking for updates
}
...
...
@@ -94,7 +94,7 @@ class Upload extends React.Component {
const
{
page
,
perPage
,
orderBy
,
order
}
=
params
this
.
setState
({
loading
:
true
})
this
.
state
.
upload
.
get
(
page
,
perPage
,
orderBy
,
order
)
this
.
state
.
upload
.
get
(
page
,
perPage
,
orderBy
,
order
===
'
asc
'
?
1
:
-
1
)
.
then
(
upload
=>
{
if
(
!
this
.
_unmounted
)
{
const
continueUpdating
=
upload
.
status
!==
'
SUCCESS
'
&&
upload
.
status
!==
'
FAILURE
'
&&
!
upload
.
is_stale
...
...
@@ -169,7 +169,7 @@ class Upload extends React.Component {
renderStepper
()
{
const
{
classes
}
=
this
.
props
const
{
upload
}
=
this
.
state
const
{
calcs
,
tasks
,
current_task
,
status
,
errors
,
waiting
}
=
upload
const
{
calcs
,
tasks
,
current_task
,
status
,
errors
}
=
upload
let
activeStep
=
tasks
.
indexOf
(
current_task
)
activeStep
+=
(
status
===
'
SUCCESS
'
)
?
1
:
0
...
...
@@ -181,7 +181,7 @@ class Upload extends React.Component {
if
(
upload
.
status
!==
'
FAILURE
'
)
{
props
.
optional
=
(
<
Typography
variant
=
"
caption
"
>
{
waiting
?
'
waiting for
upload
'
:
`
${
uploading
||
0
}
%`
}
{
uploading
===
100
&&
current_task
===
tasks
[
0
]
?
'
waiting for
processing ...
'
:
`
${
uploading
||
0
}
%`
}
<
/Typography
>
)
}
...
...
@@ -292,7 +292,7 @@ class Upload extends React.Component {
}
const
renderRow
=
(
calc
,
index
)
=>
{
const
{
mainfile
,
archive_id
,
parser
,
tasks
,
current_task
,
status
,
errors
}
=
calc
const
{
mainfile
,
calc_hash
,
upload_hash
,
parser
,
tasks
,
current_task
,
status
,
errors
}
=
calc
const
color
=
status
===
'
FAILURE
'
?
'
error
'
:
'
default
'
const
row
=
(
<
TableRow
key
=
{
index
}
>
...
...
@@ -301,7 +301,7 @@ class Upload extends React.Component {
{
mainfile
}
<
/Typography
>
<
Typography
variant
=
"
caption
"
color
=
{
color
}
>
{
archive_id
}
{
upload_hash
}
/{calc_hash
}
<
/Typography
>
<
/TableCell
>
<
TableCell
>
...
...
@@ -324,7 +324,7 @@ class Upload extends React.Component {
<
Typography
color
=
{
color
}
>
{(
status
===
'
SUCCESS
'
||
status
===
'
FAILURE
'
)
?
<
a
className
=
{
classes
.
logLink
}
href
=
"
#logs
"
onClick
=
{()
=>
this
.
setState
({
archiveLogs
:
archive_id
})}
>
<
a
className
=
{
classes
.
logLink
}
href
=
"
#logs
"
onClick
=
{()
=>
this
.
setState
({
archiveLogs
:
{
uploadHash
:
upload_hash
,
calcHash
:
calc_hash
}
})}
>
{
status
.
toLowerCase
()}
<
/a
>
:
status
.
toLowerCase
()
...
...
@@ -332,14 +332,14 @@ class Upload extends React.Component {
<
/Typography
>
<
/TableCell
>
<
TableCell
>
<
CalcLinks
calcId
=
{
archive_id
}
disabled
=
{
status
!==
'
SUCCESS
'
}
/
>
<
CalcLinks
uploadHash
=
{
upload_hash
}
calcHash
=
{
calc_hash
}
disabled
=
{
status
!==
'
SUCCESS
'
}
/
>
<
/TableCell
>
<
/TableRow
>
)
if
(
status
===
'
FAILURE
'
)
{
return
(
<
Tooltip
key
=
{
archive_id
}
title
=
{
errors
.
map
((
error
,
index
)
=>
(
<
p
key
=
{
`
${
archive_id
}
-
${
index
}
`
}
>
{
error
}
<
/p>
))
}
>
<
Tooltip
key
=
{
calc_hash
}
title
=
{
errors
.
map
((
error
,
index
)
=>
(
<
p
key
=
{
`
${
calc_hash
}
-
${
index
}
`
}
>
{
error
}
<
/p>
))
}
>
{
row
}
<
/Tooltip
>
)
...
...
@@ -392,6 +392,7 @@ class Upload extends React.Component {
<
TableCell
colSpan
=
{
6
}
/
>
<
/TableRow
>
)}
<
TableRow
>
<
TablePagination
count
=
{
total
}
...
...
@@ -414,7 +415,8 @@ class Upload extends React.Component {
onClose
=
{()
=>
this
.
setState
({
archiveLogs
:
null
})}
anchorEl
=
{
window
.
parent
.
document
.
documentElement
.
firstElementChild
}
raiseError
=
{
this
.
props
.
raiseError
}
archiveId
=
{
this
.
state
.
archiveLogs
}
uploadHash
=
{
this
.
state
.
archiveLogs
.
uploadHash
}
calcHash
=
{
this
.
state
.
archiveLogs
.
calcHash
}
/
>
)
}
else
{
...
...
nomad/api/admin.py
View file @
0600823c
...
...
@@ -28,7 +28,7 @@ ns = api.namespace('admin', description='Administrative operations')
@
api
.
doc
(
params
=
{
'operation'
:
'The operation to perform.'
})
class
AdminOperationsResource
(
Resource
):
# TODO in production this requires authorization
@
api
.
doc
(
'exec'
)
@
api
.
doc
(
'exec
_admin_command
'
)
@
api
.
response
(
200
,
'Operation performed'
)
@
api
.
response
(
404
,
'Operation does not exist'
)
@
api
.
response
(
400
,
'Operation not available/disabled'
)
...
...
nomad/api/archive.py
View file @
0600823c
...
...
@@ -22,6 +22,8 @@ import os.path
from
flask
import
send_file
from
flask_restplus
import
abort
,
Resource
import
nomad_meta_info
from
nomad
import
config
from
nomad.files
import
ArchiveFile
,
ArchiveLogFile
from
nomad.utils
import
get_logger
...
...
@@ -37,9 +39,9 @@ ns = api.namespace(
@
calc_route
(
ns
,
'/logs'
)
class
ArchiveCalcLogResource
(
Resource
):
@
api
.
doc
(
'get_logs'
)
@
api
.
doc
(
'get_
archive_
logs'
)
@
api
.
response
(
404
,
'The upload or calculation does not exist'
)
@
api
.
response
(
200
,
'Archive data send'
)
@
api
.
response
(
200
,
'Archive data send'
,
headers
=
{
'Content-Type'
:
'application/plain'
}
)
@
login_if_available
def
get
(
self
,
upload_hash
,
calc_hash
):
"""
...
...
@@ -58,7 +60,7 @@ class ArchiveCalcLogResource(Resource):
rv
=
send_file
(
archive_path
,
mimetype
=
'
application/text
'
,
mimetype
=
'
text/plain
'
,
as_attachment
=
True
,
attachment_filename
=
os
.
path
.
basename
(
archive_path
))
...
...
@@ -75,7 +77,7 @@ class ArchiveCalcLogResource(Resource):
@
calc_route
(
ns
)
class
ArchiveCalcResource
(
Resource
):
@
api
.
doc
(
'get_calc'
)
@
api
.
doc
(
'get_
archive_
calc'
)
@
api
.
response
(
404
,
'The upload or calculation does not exist'
)
@
api
.
response
(
200
,
'Archive data send'
)
@
login_if_available
...
...
@@ -112,3 +114,33 @@ class ArchiveCalcResource(Resource):
upload_hash
=
upload_hash
,
calc_hash
=
calc_hash
)
logger
.
error
(
'Exception on accessing archive'
,
exc_info
=
e
)
abort
(
500
,
message
=
'Could not accessing the archive.'
)
@
ns
.
route
(
'/metainfo/<string:metainfo_path>'
)
@
api
.
doc
(
params
=
dict
(
metainfo_path
=
'A path or metainfo definition file name.'
))
class
MetainfoResource
(
Resource
):
@
api
.
doc
(
'get_metainfo'
)
@
api
.
response
(
404
,
'The metainfo does not exist'
)
@
api
.
response
(
200
,
'Metainfo data send'
)
def
get
(
self
,
metainfo_path
):
"""
Get a metainfo definition file.
"""
try
:
file_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
nomad_meta_info
.
__file__
))
meta_info_path
=
os
.
path
.
normpath
(
os
.
path
.
join
(
file_dir
,
metainfo_path
.
strip
()))
rv
=
send_file
(
meta_info_path
,
mimetype
=
'application/json'
,
as_attachment
=
True
,
attachment_filename
=
os
.
path
.
basename
(
metainfo_path
))
return
rv
except
FileNotFoundError
:
abort
(
404
,
message
=
'The metainfo %s does not exist.'
%
metainfo_path
)
except
Exception
as
e
:
logger
=
get_logger
(
__name__
,
endpoint
=
'metainfo'
,
action
=
'get'
,
metainfo_path
=
metainfo_path
)
logger
.
error
(
'Exception on accessing metainfo'
,
exc_info
=
e
)
abort
(
500
,
message
=
'Could not accessing the metainfo.'
)
nomad/api/common.py
View file @
0600823c
...
...
@@ -38,6 +38,8 @@ pagination_request_parser.add_argument(
'per_page'
,
type
=
int
,
help
=
'Desired calcs per page.'
,
location
=
'args'
)
pagination_request_parser
.
add_argument
(
'order_by'
,
type
=
str
,
help
=
'The field to sort by.'
,
location
=
'args'
)
pagination_request_parser
.
add_argument
(
'order'
,
type
=
int
,
help
=
'Use -1 for decending and 1 for acending order.'
,
location
=
'args'
)
def
calc_route
(
ns
,
prefix
:
str
=
''
):
...
...
nomad/api/repo.py
View file @
0600823c
...
...
@@ -34,7 +34,7 @@ ns = api.namespace('repo', description='Access repository metadata, edit user me
class
RepoCalcResource
(
Resource
):
@
api
.
response
(
404
,
'The upload or calculation does not exist'
)
@
api
.
response
(
200
,
'Metadata send'
)
@
api
.
doc
(
'get_calc'
)
@
api
.
doc
(
'get_
repo_
calc'
)
def
get
(
self
,
upload_hash
,
calc_hash
):
"""
Get calculation metadata in repository form.
...
...
nomad/api/upload.py
View file @
0600823c
...
...
@@ -271,7 +271,7 @@ class UploadResource(Resource):
except
NotAllowedDuringProcessing
:
abort
(
400
,
message
=
'You must not delete an upload during processing.'
)
@
api
.
doc
(
'exec'
)
@
api
.
doc
(
'exec
_upload_command
'
)
@
api
.
response
(
404
,
'Upload does not exist or is not allowed'
)
@
api
.
response
(
400
,
'Operation is not supported'
)
@
api
.
marshal_with
(
upload_model
,
skip_none
=
True
,
code
=
200
,
description
=
'Upload unstaged successfully'
)
...
...
nomad/client.py
View file @
0600823c
...
...
@@ -74,7 +74,7 @@ def handle_common_errors(func):
return
wrapper
def
upload_file
(
file_path
:
str
,
name
:
str
=
None
,
offline
:
bool
=
False
,
unstage
:
bool
=
False
,
client
=
None
):
def
upload_file
(
file_path
:
str
,
name
:
str
=
None
,
offline
:
bool
=
False
,
unstage
:
bool
=
False
,
client
=
None
):
"""
Upload a file to nomad.
...
...
@@ -118,7 +118,7 @@ def upload_file(file_path: str, name: str = None, offline: bool = False, unstage
for
error
in
upload
.
errors
:
click
.
echo
(
' %s'
%
error
)
elif
unstage
:
client
.
uploads
.
exec
(
upload_id
=
upload
.
upload_id
,
operation
=
'unstage'
).
reponse
()
client
.
uploads
.
exec
_upload_command
(
upload_id
=
upload
.
upload_id
,
operation
=
'unstage'
).
reponse
()
return
upload
.
upload_id
...
...
@@ -300,7 +300,7 @@ def upload(path, name: str, offline: bool, unstage: bool):