Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pycalibration
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Model registry
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
calibration
pycalibration
Commits
e8b83242
Commit
e8b83242
authored
5 years ago
by
Steffen Hauf
Browse files
Options
Downloads
Patches
Plain Diff
Provide a CLI option for changing configurations
parent
c1cef4ae
No related branches found
Branches containing commit
No related tags found
Tags containing commit
1 merge request
!145
Provide a CLI option for changing configurations
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
webservice/update_config.py
+83
-0
83 additions, 0 deletions
webservice/update_config.py
webservice/webservice.py
+85
-1
85 additions, 1 deletion
webservice/webservice.py
with
168 additions
and
1 deletion
webservice/update_config.py
0 → 100644
+
83
−
0
View file @
e8b83242
import
argparse
import
json
import
sys
import
yaml
import
zmq
available_options
=
{
"
AGIPD
"
:
{
"
force-hg-if-below
"
:
float
,
"
blc-noise
"
:
bool
,
"
dont-zero-nans
"
:
bool
,
"
dont-zero-orange
"
:
bool
,
"
max-pulses
"
:
int
},
}
parser
=
argparse
.
ArgumentParser
(
description
=
'
Request update of configuration
'
)
parser
.
add_argument
(
'
--detector
'
,
type
=
str
,
choices
=
[
'
AGIPD
'
])
parser
.
add_argument
(
'
--task
'
,
type
=
str
,
choices
=
[
'
correct
'
,
'
dark
'
])
parser
.
add_argument
(
'
--proposal
'
,
type
=
str
,
help
=
'
The proposal number, without leading p, but with leading zeros
'
)
# noqa
parser
.
add_argument
(
'
--instrument
'
,
type
=
str
,
choices
=
[
"
SPB
"
,
"
MID
"
,
"
FXE
"
,
"
SCS
"
,
"
SQS
"
,
"
HED
"
,
"
DETLAB
"
],
help
=
'
The instrument
'
)
# noqa
parser
.
add_argument
(
'
--cycle
'
,
type
=
str
,
help
=
'
The facility cycle
'
)
parser
.
add_argument
(
'
--apply
'
,
action
=
'
store_true
'
)
# remove help calls as they will cause the argument parser to exit
add_help
=
False
if
"
-h
"
in
sys
.
argv
:
sys
.
argv
.
remove
(
"
-h
"
)
add_help
=
True
if
"
--help
"
in
sys
.
argv
:
sys
.
argv
.
remove
(
"
--help
"
)
add_help
=
True
known
,
remaining
=
parser
.
parse_known_args
()
args
=
vars
(
known
)
detector
=
args
[
"
detector
"
]
for
option
,
typ
in
available_options
[
detector
].
items
():
parser
.
add_argument
(
f
"
--
{
option
}
"
,
type
=
typ
)
if
add_help
:
sys
.
argv
.
append
(
"
--help
"
)
args
=
vars
(
parser
.
parse_args
())
task
=
args
[
'
task
'
]
instrument
=
args
[
'
instrument
'
]
proposal
=
args
[
'
proposal
'
]
cycle
=
args
[
'
cycle
'
]
if
task
is
None
or
instrument
is
None
or
proposal
is
None
or
cycle
is
None
:
print
(
"
Need to define all fields
"
)
exit
()
new_conf
=
{
task
:
{
instrument
:
{
detector
:
{}}}}
for
key
,
value
in
args
.
items
():
key
=
key
.
replace
(
"
_
"
,
"
-
"
)
if
key
in
available_options
[
detector
]
and
value
is
not
None
:
new_conf
[
task
][
instrument
][
detector
][
key
]
=
value
pyaml
=
yaml
.
dump
(
new_conf
,
default_flow_style
=
False
)
if
not
args
[
"
apply
"
]:
print
(
"
\n
"
)
print
(
"
-
"
*
80
)
print
(
"
THIS IS A DRY RUN ONLY, NO CHANGES ARE MADE
"
)
print
(
"
\n
"
)
print
(
"
-
"
*
80
)
print
(
f
"
Sending the following update:
\n
{
pyaml
}
"
)
print
(
"
-
"
*
80
)
con
=
zmq
.
Context
()
socket
=
con
.
socket
(
zmq
.
REQ
)
con
=
socket
.
connect
(
"
tcp://max-exfl016:5555
"
)
msg
=
"'
,
'"
.
join
([
"
update_conf
"
,
"
SASEX
"
,
args
[
"
instrument
"
],
args
[
"
cycle
"
],
args
[
"
proposal
"
],
json
.
dumps
(
new_conf
),
str
(
args
[
"
apply
"
])])
socket
.
send
(
"
[
'
{}
'
]
"
.
format
(
msg
).
encode
())
resp
=
socket
.
recv_multipart
()[
0
]
print
(
"
Configuration now in place is:
"
)
print
(
resp
.
decode
())
This diff is collapsed.
Click to expand it.
webservice/webservice.py
+
85
−
1
View file @
e8b83242
...
...
@@ -3,6 +3,7 @@ import asyncio
import
copy
import
getpass
import
glob
import
json
import
logging
import
os
import
sqlite3
...
...
@@ -112,6 +113,77 @@ async def upload_config(socket, config, yaml, instrument, cycle, proposal):
socket
.
send
(
Success
.
UPLOADED_CONFIG
.
format
(
cycle
,
proposal
).
encode
())
def
merge
(
source
,
destination
):
"""
Deep merge two dictionaries
:param source: source dictionary to merge into destination
:param destination: destination dictionary which is being merged in
:return: the updated destination dictionary
Taken from: https://stackoverflow.com/questions/20656135/python-deep-merge-dictionary-data
"""
for
key
,
value
in
source
.
items
():
if
isinstance
(
value
,
dict
):
# get node or create one
node
=
destination
.
setdefault
(
key
,
{})
merge
(
value
,
node
)
else
:
destination
[
key
]
=
value
return
destination
async
def
change_config
(
socket
,
config
,
updated_config
,
instrument
,
cycle
,
proposal
,
apply
=
False
):
"""
Change the configuration of a proposal
If no proposal specific configuration yet exists, one is first created
based on the default configuration of the proposal
Changes are committed to git.
:param socket: ZMQ socket to send reply on
:param config: repo config as given in YAML config file
:param updated_config: a dictionary containing the updated config
:param instrument: the instrument to change config for
:param cycle: the cycle to change config for
:param proposal: the proposal to change config for
:param apply: set to True to actually commit a change, otherwise a dry-run
is performed
:return: The updated config to the requesting zmq socket
"""
# first check if a proposal specific config exists, if not create one
repo
=
Repo
(
config
[
'
local-path
'
])
repo
.
remote
().
pull
()
prop_dir
=
os
.
path
.
join
(
repo
.
working_tree_dir
,
cycle
)
os
.
makedirs
(
prop_dir
,
exist_ok
=
True
)
fpath
=
"
{}/p{:06d}.yaml
"
.
format
(
prop_dir
,
int
(
proposal
))
if
not
os
.
path
.
exists
(
fpath
):
with
open
(
"
{}/default.yaml
"
.
format
(
repo
.
working_tree_dir
),
"
r
"
)
as
f
:
defconf
=
yaml
.
load
(
f
.
read
())
subconf
=
{}
for
action
,
instruments
in
defconf
.
items
():
subconf
[
action
]
=
{}
subconf
[
action
][
instrument
]
=
instruments
[
instrument
]
with
open
(
fpath
,
"
w
"
)
as
wf
:
wf
.
write
(
yaml
.
dump
(
subconf
,
default_flow_style
=
False
))
new_conf
=
None
with
open
(
fpath
,
"
r
"
)
as
rf
:
existing_conf
=
yaml
.
load
(
rf
.
read
())
new_conf
=
merge
(
updated_config
,
existing_conf
)
if
apply
:
with
open
(
fpath
,
"
w
"
)
as
wf
:
wf
.
write
(
yaml
.
dump
(
new_conf
,
default_flow_style
=
False
))
repo
.
index
.
add
([
fpath
])
repo
.
index
.
commit
(
"
Update to proposal YAML: {}
"
.
format
(
datetime
.
now
().
isoformat
()))
repo
.
remote
().
push
()
logging
.
info
(
Success
.
UPLOADED_CONFIG
.
format
(
cycle
,
proposal
))
socket
.
send
(
yaml
.
dump
(
new_conf
,
default_flow_style
=
False
).
encode
())
async
def
slurm_status
(
filter_user
=
True
):
"""
Return the status of slurm jobs by calling squeue
...
...
@@ -362,7 +434,7 @@ async def server_runner(config, mode):
action
,
payload
=
response
[
0
],
response
[
1
:]
if
action
not
in
[
"
correct
"
,
'
dark
'
,
'
query-rid
'
,
'
upload-yaml
'
]:
# only handle known actions
'
upload-yaml
'
,
'
update_conf
'
]:
# only handle known actions
logging
.
warn
(
Errors
.
UNKNOWN_ACTION
.
format
(
action
))
socket
.
send
(
Errors
.
UNKNOWN_ACTION
.
format
(
action
).
encode
())
continue
...
...
@@ -379,6 +451,18 @@ async def server_runner(config, mode):
priority
=
None
req_res
=
None
if
action
in
[
'
update_conf
'
]:
try
:
sase
,
instrument
,
cycle
,
proposal
,
config_yaml
,
apply
=
payload
# noqa
updated_config
=
json
.
loads
(
config_yaml
)
await
change_config
(
socket
,
config
[
'
config-repo
'
],
updated_config
,
instrument
,
cycle
,
proposal
,
apply
.
upper
()
==
"
TRUE
"
)
except
Exception
as
e
:
e
=
str
(
e
)
logging
.
error
(
f
"
Failure applying config for
{
proposal
}
:
"
+
"
{e}: {updated_config}
"
)
if
action
in
[
'
dark
'
,
'
correct
'
]:
wait_runs
=
[]
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment