ocaml/idl/datamodel.ml | 12 ++++++
ocaml/idl/ocaml_backend/rbac_audit.ml | 26 ++++---------
ocaml/xapi/audit_log.ml | 22 +++++++++--
ocaml/xapi/xapi_vm_clone.ml | 2 +-
ocaml/xapi/xapi_vmpp.ml | 64 +++++++++++++++++++++++++++++++++++
scripts/mail-alarm | 28 ++++++++++++++-
6 files changed, 129 insertions(+), 25 deletions(-)
# HG changeset patch
# User Marcus Granado <marcus.granado@xxxxxxxxxx>
# Date 1282322886 -3600
# Node ID 69e3ee3fb691d14532504fa5014451a9fad58be6
# Parent f8298e1caacd3a2a5323388ac9d44a4ae12bf98d
CP-1841: add new api call vmpp.get_alerts
Signed-off-by: Marcus Granado <marcus.granado@xxxxxxxxxxxxx>
diff -r f8298e1caacd -r 69e3ee3fb691 ocaml/idl/datamodel.ml
--- a/ocaml/idl/datamodel.ml
+++ b/ocaml/idl/datamodel.ml
@@ -5875,6 +5875,17 @@
~allowed_roles:_R_VM_POWER_ADMIN
~result:(String, "An XMLRPC result")
()
+let vmpp_get_alerts = call ~flags:[`Session]
+ ~name:"get_alerts"
+ ~in_oss_since:None
+ ~in_product_since:rel_cowley
+ ~params:[Ref _vmpp, "vmpp", "The protection policy";
+ DateTime, "since", "oldest record to fetch";
+ ]
+ ~doc:"This call fetches a history of alerts for a given protection policy"
+ ~allowed_roles:_R_POOL_OP
+ ~result:(Set (String), "A list of alerts encoded in xml")
+ ()
let vmpp_backup_type = Enum ("vmpp_backup_type",
[
"snapshot", "The backup is a snapshot";
@@ -6105,6 +6116,7 @@
~messages:[
vmpp_protect_now;
vmpp_archive_now;
+ vmpp_get_alerts;
vmpp_set_is_backup_running;
vmpp_set_is_archive_running;
vmpp_set_backup_frequency;
diff -r f8298e1caacd -r 69e3ee3fb691 ocaml/idl/ocaml_backend/rbac_audit.ml
--- a/ocaml/idl/ocaml_backend/rbac_audit.ml
+++ b/ocaml/idl/ocaml_backend/rbac_audit.ml
@@ -81,26 +81,14 @@
let get_subject_name __context session_id =
get_subject_common ~__context ~session_id
~fnname:"get_subject_name"
- ~fn_if_local_session:(fun()->"")
- ~fn_if_local_superuser:(fun()->"")
+ ~fn_if_local_session:(fun()->
+ DB_Action.Session.get_auth_user_name ~__context
~self:session_id
+ )
+ ~fn_if_local_superuser:(fun()->
+ DB_Action.Session.get_auth_user_name ~__context
~self:session_id
+ )
~fn_if_subject:(fun()->
DB_Action.Session.get_auth_user_name ~__context
~self:session_id
- (*
- let sid =
- DB_Action.Session.get_auth_user_sid ~__context
~self:session_id
- in
- let subjs = DB_Action.Subject.get_records_where
~__context
- ~expr:(Eq(Field "subject_identifier", Literal
(sid)))
- in
- if List.length subjs > 1 then
- failwith (Printf.sprintf
- "More than one subject for
subject_identifier %s"sid
- );
- let (subj_id,subj) = List.hd subjs in
- List.assoc
- "subject-name"
(*Auth_signature.subject_information_field_subject_name*)
- subj.API.subject_other_config
- *)
)
(*given a ref-value, return a human-friendly value associated with that ref*)
@@ -209,6 +197,8 @@
("host.enable_external_auth",["service_name";"auth_type"]);
("subject.create",["subject_identifier";"other_config"]);
("subject.create.other_config",["subject-name"]);
+ (* used for VMPP alert logs *)
+ ("message.create",["name";"body"]);
]
(* manual ref getters *)
diff -r f8298e1caacd -r 69e3ee3fb691 ocaml/xapi/audit_log.ml
--- a/ocaml/xapi/audit_log.ml
+++ b/ocaml/xapi/audit_log.ml
@@ -26,7 +26,16 @@
let timestamp_index line =
try ((String.index line '[') + 1) with Not_found -> 0
-let write_line line fd since =
+let went_through ?filter line =
+ match filter with
+ |None->true
+ |Some fs->
+ List.fold_left
+ (fun acc f->acc&&(String.has_substr line f))
+ true
+ fs
+
+let write_line line fd ?filter since =
if String.length line >
(line_timestamp_length + (timestamp_index line))
then
@@ -35,10 +44,12 @@
in
if since="" or ((String.compare line_timestamp since) >= 0)
then
+ if went_through ?filter line
+ then
let len = String.length line in
ignore(Unix.write fd line 0 len)
-let transfer_audit_file _path compression fd_out since =
+let transfer_audit_file _path compression fd_out ?filter since =
let path = Unixext.resolve_dot_and_dotdot _path in
let in_whitelist = (String.startswith audit_log_whitelist_prefix path)
in
if in_whitelist then
@@ -50,7 +61,7 @@
if compression="" (* uncompressed *)
then begin
Unixext.readfile_line
- (fun line -> write_line (line^"\n")
fd_out since)
+ (fun line -> write_line (line^"\n")
fd_out ?filter since)
path
end
else if compression="gz"
@@ -63,7 +74,7 @@
try
while
true do
let line = input_line cin in
-
write_line (line^"\n") fd_out since
+
write_line (line^"\n") fd_out ?filter since
done
with
End_of_file -> () (* ok, expected *)
)
@@ -79,7 +90,7 @@
end
end
-let transfer_all_audit_files fd_out since =
+let transfer_all_audit_files fd_out ?filter since =
let atransfer _infix _suffix =
let infix = if _infix="" then "" else "."^_infix in
let suffix = if _suffix="" then "" else "."^_suffix in
@@ -87,6 +98,7 @@
(audit_log_whitelist_prefix^infix^suffix)
_suffix
fd_out
+ ?filter
since
in
let atransfer_try_gz infix =
diff -r f8298e1caacd -r 69e3ee3fb691 ocaml/xapi/xapi_vm_clone.ml
--- a/ocaml/xapi/xapi_vm_clone.ml
+++ b/ocaml/xapi/xapi_vm_clone.ml
@@ -254,7 +254,7 @@
(let session = Context.get_session_id __context in
let uname = Db.Session.get_auth_user_name ~__context ~self:session in
let is_lsu = Db.Session.get_is_local_superuser ~__context ~self:session
in
- is_lsu && (uname = "__dom0__vmpr")
+ is_lsu && (uname = Xapi_vmpp.vmpr_username)
)
with e ->
debug "Error obtaining is_snapshot_from_vmpp: %s" (Printexc.to_string e);
diff -r f8298e1caacd -r 69e3ee3fb691 ocaml/xapi/xapi_vmpp.ml
--- a/ocaml/xapi/xapi_vmpp.ml
+++ b/ocaml/xapi/xapi_vmpp.ml
@@ -15,6 +15,7 @@
open D
let vmpr_plugin = "vmpr"
+let vmpr_username = "__dom0__vmpr"
let protect_now ~__context ~vmpp =
let vmpp_uuid = Db.VMPP.get_uuid ~__context ~self:vmpp in
@@ -34,6 +35,69 @@
"archive_now"
args
+let add_alert ~__context ~vmpp ~name ~priority ~body =
+ ()
+
+let get_alerts ~__context ~vmpp ~since =
+ let vmpp_uuid = Db.VMPP.get_uuid ~__context ~self:vmpp in
+ let filter=["unix-RPC|message.create";vmpr_username;vmpp_uuid] in
+ let tmp_filename = Filename.temp_file "vmpp-alerts-" ".dat" in
+ let fd = Unix.openfile tmp_filename [Unix.O_RDWR] 0o600 in
+ let since = Date.to_string since in
+ let messages=Audit_log.transfer_all_audit_files fd ~filter since in
+ let cout = Unix.out_channel_of_descr fd in
+ flush cout;
+ let cin = Unix.in_channel_of_descr fd in
+ seek_in cin 0;
+ let lines = ref [] in
+ let i = ref 0 in (* hard limit on maximum number of lines to parse *)
+ (try while !i<1000 do let line = input_line cin in lines:=line::!lines;
i:=!i+1 done with End_of_file->());
+ let lines = !lines in
+ Unix.close fd;
+ Sys.remove tmp_filename;
+ let alerts = List.map (fun line->
+ let sexpr_init = try (String.index line ']')+1 with Not_found -> -1 in
+ if sexpr_init>=0 && sexpr_init<(String.length line) then (
+ let sexpr_str = Stringext.String.sub_to_end line
sexpr_init in
+ let (sroot:SExpr.t) =
+ (try SExpr_TS.of_string sexpr_str
+ with e->
+ debug "error %s parsing sexpr: %s"
+ (ExnHelper.string_of_exn e) sexpr_str
+ ;
+ (SExpr.Node [])
+ )
+ in
+ match sroot with
+ |SExpr.Node (SExpr.String _::SExpr.String
_::SExpr.String _::SExpr.String _::SExpr.String _::SExpr.String _::SExpr.String
_::SExpr.Node params::[])->(
+ let kvs = List.fold_right (fun (sexpr:SExpr.t) acc ->
+ match sexpr with
+ |SExpr.Node (SExpr.String name::SExpr.String
value::SExpr.String _::SExpr.String _::[]) when name="name" or name="body"->
+ (name,value)::acc
+ |_->acc
+ ) params []
+ in
+ if kvs=[] then None else Some kvs
+ )
+ |_->None
+ )
+ else None
+ ) lines
+ in
+ let alerts = List.fold_right (fun a acc->match a with None->acc|Some
a->a::acc) alerts [] in
+ let inside_data_tag str =
+ let tag_begin="<data>" and tag_end="</data>" in
+ let tag_begin_idx=try List.hd (Stringext.String.find_all tag_begin str)
with _-> -1 in
+ let tag_end_idx=try List.hd (List.rev (Stringext.String.find_all tag_end
str)) with _-> -1 in
+ try
+ let start=(tag_begin_idx+(String.length tag_begin)) in
+ let len=tag_end_idx - start in
+ Some (String.sub str start len)
+ with _->None
+ in
+ let alerts = List.fold_right (fun a acc->if List.mem_assoc "body" a then
(let data=inside_data_tag(List.assoc "body" a) in match data with
None->acc|Some data->data::acc) else acc) alerts [] in
+ alerts
+
let set_is_backup_running ~__context ~self ~value =
Db.VMPP.set_is_backup_running ~__context ~self ~value
diff -r f8298e1caacd -r 69e3ee3fb691 scripts/mail-alarm
--- a/scripts/mail-alarm
+++ b/scripts/mail-alarm
@@ -17,6 +17,7 @@
import traceback
import syslog
from xml.dom import minidom
+from xml.sax.saxutils import unescape
from xml.parsers.expat import ExpatError
from socket import getfqdn
@@ -286,6 +287,29 @@
'This alarm is set to be triggered when a host belonging to a high
availability pool fails.' \
'\n' % self.text
+class VmppETG(EmailTextGenerator):
+ def __init__(self, msg):
+ self.msg = msg
+
+ def generate_subject(self):
+ msg = self.msg
+ return "[%s] XenServer Message: %s %s %s" % (msg.pool_name, msg.cls,
msg.obj_uuid, msg.name)
+
+ def generate_body(self):
+ msg = self.msg
+ msg_body = unescape(msg.body)
+ try:
+ xmldoc = minidom.parseString(msg_body)
+ body_message = xmldoc.getElementsByTagName('message')[0]
+ email_message =
body_message.getElementsByTagName('email')[0].firstChild.data
+ return \
+
"Field\t\tValue\n-----\t\t-----\nName:\t\t%s\nPriority:\t%s\nClass:\t\t%s\n" \
+ "Object UUID:\t%s\nTimestamp:\t%s\nMessage UUID:\t%s\nPool
name:\t%s\nBody:\t\t%s\n" % \
+
(msg.name,msg.priority,msg.cls,msg.obj_uuid,msg.timestamp,msg.uuid,msg.pool_name,email_message)
+ except:
+ log_err("Badly formatted XML, or missing field")
+ sys.exit(1)
+
class XapiMessage:
def __init__(self, xml):
"Parse message XML"
@@ -322,7 +346,9 @@
if hasattr(self,'cached_etg'):
return self.cached_etg
- if self.name == 'ALARM':
+ if self.cls == 'VMPP':
+ etg = VmppETG(self)
+ elif self.name == 'ALARM':
# Extract the current level of the variable
# (this will raise an exception if the 1st line of <body> is not
in the correct format, namely "value: %f\n")
value_line = self.body.split("\n",2)[0]
xen-api.hg-13.patch
Description: Text Data
_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
|