Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
alarm-mail
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
cs
ds
alarm-mail
Commits
da0446aa
Commit
da0446aa
authored
3 years ago
by
Graziano Scalamera
Browse files
Options
Downloads
Patches
Plain Diff
Add support for alarm-notify
parent
bf88c97c
No related branches found
Branches containing commit
Tags
1.2.5
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/AlarmMail.py
+272
-81
272 additions, 81 deletions
src/AlarmMail.py
src/AlarmMail.xmi
+27
-0
27 additions, 0 deletions
src/AlarmMail.xmi
with
299 additions
and
81 deletions
src/AlarmMail.py
+
272
−
81
View file @
da0446aa
...
...
@@ -247,6 +247,30 @@ class AlarmMail (PyTango.Device_4Impl):
except
KeyError
,
e
:
url
=
''
print
e
handler_text
=
''
handler_html
=
''
try
:
handler_text
=
'
\n
Handler:
'
+
params
[
'
handler
'
]
handler_html
=
'
<br>Handler:
'
+
params
[
'
handler
'
]
except
KeyError
,
e
:
handler_text
=
''
handler_html
=
''
state_text
=
''
state_html
=
''
try
:
state_text
=
'
\n
State:
'
+
params
[
'
state
'
]
state_html
=
'
<br>State:
'
+
params
[
'
state
'
]
except
KeyError
,
e
:
state_text
=
''
state_html
=
''
ack_text
=
''
ack_html
=
''
try
:
ack_text
=
'
\n
Ack:
'
+
params
[
'
ack
'
]
ack_html
=
'
<br>Ack:
'
+
params
[
'
ack
'
]
except
KeyError
,
e
:
ack_text
=
''
ack_html
=
''
starter_msg_text
=
''
starter_msg_html
=
''
...
...
@@ -256,40 +280,47 @@ class AlarmMail (PyTango.Device_4Impl):
if
len
(
url
)
==
0
:
if
len
(
msg_link
)
==
0
:
msg
=
MIMEText
(
'
NEW ALARM DETECTED:
\n
Name:
'
+
params
[
'
name
'
]
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
]
+
starter_msg_text
)
msg
=
MIMEText
(
'
NEW ALARM DETECTED:
\n
Name:
'
+
params
[
'
name
'
]
+
handler_text
+
state_text
+
ack_text
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
]
+
starter_msg_text
)
else
:
msg
=
MIMEText
(
'
<html><head></head><body><p>NEW ALARM DETECTED: <br>Name:
'
+
params
[
'
name
'
]
+
'
<br>Message:
'
+
params
[
'
msg
'
]
+
'
<br>Values:
'
+
params
[
'
values
'
]
+
'
<br>Formula:
'
+
params
[
'
formula
'
]
+
'
<br><br>HDB++ eGiga link:<br><br>
'
+
msg_link
+
starter_msg_html
+
'
</p></body></html>
'
,
'
html
'
)
msg
=
MIMEText
(
'
<html><head></head><body><p>NEW ALARM DETECTED: <br>Name:
'
+
params
[
'
name
'
]
+
handler_html
+
state_html
+
ack_html
+
'
<br>Message:
'
+
params
[
'
msg
'
]
+
'
<br>Values:
'
+
params
[
'
values
'
]
+
'
<br>Formula:
'
+
params
[
'
formula
'
]
+
'
<br><br>HDB++ eGiga link:<br><br>
'
+
msg_link
+
starter_msg_html
+
'
</p></body></html>
'
,
'
html
'
)
else
:
alm_url
=
'
<a href=
"'
+
url
+
'"
>
'
+
url
+
'
</a>
'
if
len
(
msg_link
)
==
0
:
msg
=
MIMEText
(
'
<html><head></head><body><p>NEW ALARM DETECTED: <br>Name:
'
+
params
[
'
name
'
]
+
'
<br>Message:
'
+
params
[
'
msg
'
]
+
'
<br>Alarm URL:
'
+
alm_url
+
'
<br>Values:
'
+
params
[
'
values
'
]
+
'
<br>Formula:
'
+
params
[
'
formula
'
]
+
starter_msg_html
+
'
</p></body></html>
'
,
'
html
'
)
msg
=
MIMEText
(
'
<html><head></head><body><p>NEW ALARM DETECTED: <br>Name:
'
+
params
[
'
name
'
]
+
handler_html
+
state_html
+
ack_html
+
'
<br>Message:
'
+
params
[
'
msg
'
]
+
'
<br>Alarm URL:
'
+
alm_url
+
'
<br>Values:
'
+
params
[
'
values
'
]
+
'
<br>Formula:
'
+
params
[
'
formula
'
]
+
starter_msg_html
+
'
</p></body></html>
'
,
'
html
'
)
else
:
msg
=
MIMEText
(
'
<html><head></head><body><p>NEW ALARM DETECTED: <br>Name:
'
+
params
[
'
name
'
]
+
'
<br>Message:
'
+
params
[
'
msg
'
]
+
'
<br>Alarm URL:
'
+
alm_url
+
'
<br>Values:
'
+
params
[
'
values
'
]
+
'
<br>Formula:
'
+
params
[
'
formula
'
]
+
'
<br><br>HDB++ eGiga link:<br><br>
'
+
msg_link
+
starter_msg_html
+
'
</p></body></html>
'
,
'
html
'
)
msg
[
'
Subject
'
]
=
'
ALARMED
'
+
params
[
'
name
'
]
+
'
-
'
+
params
[
'
msg
'
]
msg
[
'
From
'
]
=
'"'
+
self
.
email_name
+
'"
<
'
+
self
.
email_user
+
'
>
'
groups
=
params
[
'
groups
'
]
receive
=
''
first
=
True
for
gr
in
groups
.
split
(
'
|
'
):
#print('looping gr=' + gr)
try
:
#print(' -> address=' + self.addressBook[gr])
if
first
:
receive
=
receive
+
self
.
addressBook
[
gr
]
first
=
False
else
:
receive
=
receive
+
'
,
'
+
self
.
addressBook
[
gr
]
except
KeyError
,
e
:
print
'
Cannot find email address for group
'
,
gr
print
e
#print('msg to=' + receive)
msg
[
'
To
'
]
=
receive
#msg['To'] = self.addressBook[groups] + ','
s
=
smtplib
.
SMTP
(
self
.
email_smtp
)
s
.
sendmail
(
self
.
email_user
,
msg
[
"
To
"
].
split
(
"
,
"
),
msg
.
as_string
())
s
.
quit
()
msg
=
MIMEText
(
'
<html><head></head><body><p>NEW ALARM DETECTED: <br>Name:
'
+
params
[
'
name
'
]
+
handler_html
+
state_html
+
ack_html
+
'
<br>Message:
'
+
params
[
'
msg
'
]
+
'
<br>Alarm URL:
'
+
alm_url
+
'
<br>Values:
'
+
params
[
'
values
'
]
+
'
<br>Formula:
'
+
params
[
'
formula
'
]
+
'
<br><br>HDB++ eGiga link:<br><br>
'
+
msg_link
+
starter_msg_html
+
'
</p></body></html>
'
,
'
html
'
)
self
.
SendMail
(
params
,
msg
,
'
ALARMED
'
)
#----- PROTECTED REGION END -----# // AlarmMail.SendAlarm
def
SendNormal
(
self
,
argin
):
...
...
@@ -303,33 +334,30 @@ class AlarmMail (PyTango.Device_4Impl):
}
for
param
in
argin
.
split
(
'
;
'
):
params
[
param
.
split
(
'
=
'
,
1
)[
0
]]
=
param
.
split
(
'
=
'
,
1
)[
1
]
#print('looping param=' + param)
#print(params)
msg
=
MIMEText
(
'
RESTORED TO NORMAL CONDITION:
\n
Name:
'
+
params
[
'
name
'
]
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
])
msg
[
'
Subject
'
]
=
'
RESTORED
'
+
params
[
'
name
'
]
+
'
-
'
+
params
[
'
msg
'
]
msg
[
'
From
'
]
=
'"'
+
self
.
email_name
+
'"
<
'
+
self
.
email_user
+
'
>
'
groups
=
params
[
'
groups
'
]
receive
=
''
first
=
True
for
gr
in
groups
.
split
(
'
|
'
):
#print('looping gr=' + gr)
try
:
#print(' -> address=' + self.addressBook[gr])
if
first
:
receive
=
receive
+
self
.
addressBook
[
gr
]
first
=
False
else
:
receive
=
receive
+
'
,
'
+
self
.
addressBook
[
gr
]
except
KeyError
,
e
:
print
'
Cannot find email address for group
'
,
gr
print
e
#print('groups split=' + groups.split('|'))
#print('msg to=' + receive)
msg
[
'
To
'
]
=
receive
#msg['To'] = self.addressBook[groups] + ','
s
=
smtplib
.
SMTP
(
self
.
email_smtp
)
s
.
sendmail
(
self
.
email_user
,
msg
[
"
To
"
].
split
(
"
,
"
),
msg
.
as_string
())
s
.
quit
()
handler
=
''
try
:
handler
=
'
\n
Handler:
'
+
params
[
'
handler
'
]
except
KeyError
,
e
:
handler
=
''
state
=
''
try
:
state
=
'
\n
State:
'
+
params
[
'
state
'
]
except
KeyError
,
e
:
state
=
''
ack
=
''
try
:
ack
=
'
\n
Ack:
'
+
params
[
'
ack
'
]
except
KeyError
,
e
:
ack
=
''
msg
=
MIMEText
(
'
RESTORED TO NORMAL CONDITION:
\n
Name:
'
+
params
[
'
name
'
]
+
handler
+
state
+
ack
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
])
self
.
SendMail
(
params
,
msg
,
'
RESTORED
'
)
#----- PROTECTED REGION END -----# // AlarmMail.SendNormal
def
SendAlarmHDB
(
self
,
argin
):
...
...
@@ -376,31 +404,30 @@ class AlarmMail (PyTango.Device_4Impl):
for
iii
in
comb_list
:
if
len
(
iii
[
1
])
>
0
:
msg_hdb
+=
iii
[
0
]
+
'
\n
'
+
iii
[
1
]
+
'
\n\n
'
msg
=
MIMEText
(
'
NEW ALARM DETECTED:
\n
Name:
'
+
params
[
'
name
'
]
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
]
+
'
\n\n
HDB++ Errors:
\n\n
'
+
msg_hdb
)
msg
[
'
Subject
'
]
=
'
ALARMED
'
+
params
[
'
name
'
]
+
'
-
'
+
params
[
'
msg
'
]
msg
[
'
From
'
]
=
'"'
+
self
.
email_name
+
'"
<
'
+
self
.
email_user
+
'
>
'
groups
=
params
[
'
groups
'
]
receive
=
''
first
=
True
for
gr
in
groups
.
split
(
'
|
'
):
#print('looping gr=' + gr)
try
:
#print(' -> address=' + self.addressBook[gr])
if
first
:
receive
=
receive
+
self
.
addressBook
[
gr
]
first
=
False
else
:
receive
=
receive
+
'
,
'
+
self
.
addressBook
[
gr
]
except
KeyError
,
e
:
print
'
Cannot find email address for group
'
,
gr
print
e
#print('groups split=' + groups.split('|'))
#print('msg to=' + receive)
msg
[
'
To
'
]
=
receive
#msg['To'] = self.addressBook[groups] + ','
s
=
smtplib
.
SMTP
(
self
.
email_smtp
)
s
.
sendmail
(
self
.
email_user
,
msg
[
"
To
"
].
split
(
"
,
"
),
msg
.
as_string
())
s
.
quit
()
handler
=
''
try
:
handler
=
'
\n
Handler:
'
+
params
[
'
handler
'
]
except
KeyError
,
e
:
handler
=
''
state
=
''
try
:
state
=
'
\n
State:
'
+
params
[
'
state
'
]
except
KeyError
,
e
:
state
=
''
ack
=
''
try
:
ack
=
'
\n
Ack:
'
+
params
[
'
ack
'
]
except
KeyError
,
e
:
ack
=
''
msg
=
MIMEText
(
'
NEW ALARM DETECTED:
\n
Name:
'
+
params
[
'
name
'
]
+
handler
+
state
+
ack
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
]
+
'
\n\n
HDB++ Errors:
\n\n
'
+
msg_hdb
)
self
.
SendMail
(
params
,
msg
,
'
ALARMED
'
)
#----- PROTECTED REGION END -----# // AlarmMail.SendAlarmHDB
def
SendAlarmPROCFS
(
self
,
argin
):
...
...
@@ -413,6 +440,161 @@ class AlarmMail (PyTango.Device_4Impl):
self
.
SendAlarm
(
argin
)
#----- PROTECTED REGION END -----# // AlarmMail.SendAlarmPROCFS
def
SendNotification
(
self
,
argin
):
"""
:param argin:
Semicolon separated arguments, ex:
name=tagname;values={``alarm/beamstatus/0/medium2[0]``:0};url=;msg=``Test alarm``;formula=(alarm/beamstatus/0/medium2 == 1);groups=gr_ctrl;state=RTNUN;ack=0;dest= name@elettra.eu,;
:type argin: PyTango.DevString
"""
self
.
debug_stream
(
"
In SendNotification()
"
)
#----- PROTECTED REGION ID(AlarmMail.SendNotification) ENABLED START -----#
params
=
{
}
for
param
in
argin
.
split
(
'
;
'
):
params
[
param
.
split
(
'
=
'
,
1
)[
0
]]
=
param
.
split
(
'
=
'
,
1
)[
1
]
print
(
params
)
name
=
params
[
'
name
'
]
state
=
params
[
'
state
'
]
hdbppes
=
False
word
=
'
([a-zA-Z0-9\+\._\*\#\-]+)
'
word2
=
'
([a-zA-Z0-9\+\.\*\#\-]+)
'
m
=
re
.
compile
(
word
+
"
/
"
+
word
+
"
/
"
+
word
+
"
/
"
+
word
).
match
(
name
)
if
m
is
not
None
:
hdbppes
=
True
else
:
m
=
re
.
compile
(
"
hdbppes_
"
+
word2
+
"
_
"
+
word2
).
match
(
name
)
if
m
is
not
None
:
hdbppes
=
True
if
state
in
[
'
NORM
'
,
'
RTNUN
'
]:
self
.
SendNormal
(
argin
)
elif
state
in
[
'
UNACK
'
,
'
ACKED
'
]:
if
hdbppes
:
self
.
SendAlarmHDB
(
argin
)
else
:
self
.
SendAlarm
(
argin
)
elif
state
in
[
'
OOSRV
'
,
'
SHLVD
'
]:
self
.
SendDisabled
(
argin
)
elif
state
in
[
'
ERROR
'
]:
self
.
SendError
(
argin
)
#----- PROTECTED REGION END -----# // AlarmMail.SendNotification
def
SendDisabled
(
self
,
argin
):
"""
:param argin:
:type argin: PyTango.DevString
"""
self
.
debug_stream
(
"
In SendDisabled()
"
)
#----- PROTECTED REGION ID(AlarmMail.SendDisabled) ENABLED START -----#
params
=
{
}
for
param
in
argin
.
split
(
'
;
'
):
params
[
param
.
split
(
'
=
'
,
1
)[
0
]]
=
param
.
split
(
'
=
'
,
1
)[
1
]
disbled_type
=
''
if
params
[
'
state
'
]
in
[
'
OOSRV
'
]:
disbled_type
=
'
permanently (OutOfService)
'
elif
params
[
'
state
'
]
in
[
'
SHLVD
'
]:
disbled_type
=
'
for
'
+
params
[
'
shlvd_time
'
]
+
'
minutes (Shelved)
'
handler
=
''
try
:
handler
=
'
\n
Handler:
'
+
params
[
'
handler
'
]
except
KeyError
,
e
:
handler
=
''
state
=
''
try
:
state
=
'
\n
State:
'
+
params
[
'
state
'
]
except
KeyError
,
e
:
state
=
''
ack
=
''
try
:
ack
=
'
\n
Ack:
'
+
params
[
'
ack
'
]
except
KeyError
,
e
:
ack
=
''
msg
=
MIMEText
(
'
DISABLED
'
+
disbled_type
+
'
:
\n
Name:
'
+
params
[
'
name
'
]
+
handler
+
state
+
ack
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
])
self
.
SendMail
(
params
,
msg
,
'
DISABLED
'
)
#----- PROTECTED REGION END -----# // AlarmMail.SendDisabled
def
SendError
(
self
,
argin
):
"""
:param argin:
:type argin: PyTango.DevString
"""
self
.
debug_stream
(
"
In SendError()
"
)
#----- PROTECTED REGION ID(AlarmMail.SendError) ENABLED START -----#
params
=
{
}
for
param
in
argin
.
split
(
'
;
'
):
params
[
param
.
split
(
'
=
'
,
1
)[
0
]]
=
param
.
split
(
'
=
'
,
1
)[
1
]
handler
=
''
try
:
handler
=
'
\n
Handler:
'
+
params
[
'
handler
'
]
except
KeyError
,
e
:
handler
=
''
state
=
''
try
:
state
=
'
\n
State:
'
+
params
[
'
state
'
]
except
KeyError
,
e
:
state
=
''
ack
=
''
try
:
ack
=
'
\n
Ack:
'
+
params
[
'
ack
'
]
except
KeyError
,
e
:
ack
=
''
msg
=
MIMEText
(
'
ERROR evaluating alarm:
\n
Name:
'
+
params
[
'
name
'
]
+
handler
+
state
+
ack
+
'
\n
Message:
'
+
params
[
'
msg
'
]
+
'
\n
Values:
'
+
params
[
'
values
'
]
+
'
\n
Formula:
'
+
params
[
'
formula
'
])
self
.
SendMail
(
params
,
msg
,
'
ERROR
'
)
#----- PROTECTED REGION END -----# // AlarmMail.SendError
def
SendMail
(
self
,
params
,
msg
,
subject
):
self
.
debug_stream
(
"
In SendMail()
"
)
msg
[
'
Subject
'
]
=
subject
+
'
'
+
params
[
'
name
'
]
+
'
-
'
+
params
[
'
msg
'
]
msg
[
'
From
'
]
=
'"'
+
self
.
email_name
+
'"
<
'
+
self
.
email_user
+
'
>
'
receive
=
''
dest
=
''
try
:
dest
=
params
[
'
dest
'
]
except
KeyError
,
e
:
dest
=
''
if
len
(
dest
)
==
0
:
groups
=
params
[
'
groups
'
]
first
=
True
for
gr
in
groups
.
split
(
'
|
'
):
#print('looping gr=' + gr)
try
:
#print(' -> address=' + self.addressBook[gr])
if
first
:
receive
=
receive
+
self
.
addressBook
[
gr
]
first
=
False
else
:
receive
=
receive
+
'
,
'
+
self
.
addressBook
[
gr
]
except
KeyError
,
e
:
print
'
Cannot find email address for group
'
,
gr
print
e
else
:
receive
=
dest
#print('msg to=' + receive)
msg
[
'
To
'
]
=
receive
#msg['To'] = self.addressBook[groups] + ','
s
=
smtplib
.
SMTP
(
self
.
email_smtp
)
s
.
sendmail
(
self
.
email_user
,
msg
[
"
To
"
].
split
(
"
,
"
),
msg
.
as_string
())
s
.
quit
()
#----- PROTECTED REGION ID(AlarmMail.programmer_methods) ENABLED START -----#
...
...
@@ -485,6 +667,15 @@ class AlarmMailClass(PyTango.DeviceClass):
'
SendAlarmPROCFS
'
:
[[
PyTango
.
DevString
,
"
none
"
],
[
PyTango
.
DevVoid
,
"
none
"
]],
'
SendNotification
'
:
[[
PyTango
.
DevString
,
"
Semicolon separated arguments, ex:
\n
name=tagname;values={``alarm/beamstatus/0/medium2[0]``:0};url=;msg=``Test alarm``;formula=(alarm/beamstatus/0/medium2 == 1);groups=gr_ctrl;state=RTNUN;ack=0;dest= name@elettra.eu,;
"
],
[
PyTango
.
DevVoid
,
"
none
"
]],
'
SendDisabled
'
:
[[
PyTango
.
DevString
,
"
none
"
],
[
PyTango
.
DevVoid
,
"
none
"
]],
'
SendError
'
:
[[
PyTango
.
DevString
,
"
none
"
],
[
PyTango
.
DevVoid
,
"
none
"
]],
}
...
...
This diff is collapsed.
Click to expand it.
src/AlarmMail.xmi
+
27
−
0
View file @
da0446aa
...
...
@@ -97,6 +97,33 @@
</argout>
<status
abstract=
"false"
inherited=
"false"
concrete=
"true"
concreteHere=
"true"
/>
</commands>
<commands
name=
"SendNotification"
description=
""
execMethod=
"send_notification"
displayLevel=
"OPERATOR"
polledPeriod=
"0"
isDynamic=
"false"
>
<argin
description=
"Semicolon separated arguments, ex:
name=tagname;values={``alarm/beamstatus/0/medium2[0]``:0};url=;msg=``Test alarm``;formula=(alarm/beamstatus/0/medium2 == 1);groups=gr_ctrl;state=RTNUN;ack=0;dest= name@elettra.eu,;"
>
<type
xsi:type=
"pogoDsl:StringType"
/>
</argin>
<argout
description=
""
>
<type
xsi:type=
"pogoDsl:VoidType"
/>
</argout>
<status
abstract=
"false"
inherited=
"false"
concrete=
"true"
concreteHere=
"true"
/>
</commands>
<commands
name=
"SendDisabled"
description=
""
execMethod=
"send_disabled"
displayLevel=
"OPERATOR"
polledPeriod=
"0"
isDynamic=
"false"
>
<argin
description=
""
>
<type
xsi:type=
"pogoDsl:StringType"
/>
</argin>
<argout
description=
""
>
<type
xsi:type=
"pogoDsl:VoidType"
/>
</argout>
<status
abstract=
"false"
inherited=
"false"
concrete=
"true"
concreteHere=
"true"
/>
</commands>
<commands
name=
"SendError"
description=
""
execMethod=
"send_error"
displayLevel=
"OPERATOR"
polledPeriod=
"0"
isDynamic=
"false"
>
<argin
description=
""
>
<type
xsi:type=
"pogoDsl:StringType"
/>
</argin>
<argout
description=
""
>
<type
xsi:type=
"pogoDsl:VoidType"
/>
</argout>
<status
abstract=
"false"
inherited=
"false"
concrete=
"true"
concreteHere=
"true"
/>
</commands>
<preferences
docHome=
"./doc_html"
makefileHome=
"/usr/local/tango-9.3.3/share/pogo/preferences"
/>
</classes>
</pogoDsl:PogoSystem>
This diff is collapsed.
Click to expand it.
Preview
0%
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