fix rspec formatting
[sfa.git] / sfa / rspecs / rspec.py
1 #!/usr/bin/python 
2 from lxml import etree
3 from StringIO import StringIO
4 from datetime import datetime, timedelta
5 from sfa.util.xrn import *
6 from sfa.util.plxrn import hostname_to_urn
7 from sfa.util.config import Config  
8 from sfa.util.faults import SfaNotImplemented, InvalidRSpec
9
10 class RSpec:
11     header = '<?xml version="1.0"?>\n'
12     template = """<RSpec></RSpec>"""
13     namespaces = {}
14     config = Config()
15     xml = None
16   
17     def __init__(self, rspec="", namespaces={}):
18         if rspec:
19             self.parse_rspec(rspec, namespaces)
20         else:
21             self.create()
22
23     def create(self, type="advertisement"):
24         # eg. 2011-03-23T19:53:28Z 
25         date_format = '%Y-%m-%dT%H:%M:%SZ'
26         now = datetime.utcnow()
27         generated_ts = now.strftime(date_format)
28         expires_ts = (now + timedelta(hours=1)).strftime(date_format) 
29         self.parse_rspec(self.template, self.namespaces)
30         self.xml.set('valid_until', expires_ts)
31         self.xml.set('generated', generated_ts)
32     
33     def parse_rspec(self, rspec, namespaces={}):
34         parser = etree.XMLParser(remove_blank_text=True)
35         try:
36             tree = etree.parse(rspec, parser)
37         except IOError:
38             # 'rspec' file doesnt exist. 'rspec' is proably an xml string
39             try:
40                 tree = etree.parse(StringIO(rspec), parser)
41             except:
42                 raise InvalidRSpec('Must specify a xml file or xml string. Received: ' + rspec )
43
44         self.xml = tree.getroot()  
45         if namespaces:
46            self.namespaces = namespaces
47
48     def add_attribute(self, elem, name, value):
49         opt = etree.SubElement(elem, name)
50         opt.text = value
51
52     def remove_attribute(self, elem, name, value):
53         if elem is not None:
54             opts = elem.iterfind(name)
55             if opts is not None:
56                 for opt in opts:
57                     if opt.text == value:
58                         elem.remove(opt)
59
60
61     def validate(self, schema):
62         relaxng_doc = etree.parse(schema)
63         relaxng = etree.RelaxNG(relaxng_doc)
64         if not relaxng(self.xml):
65             error = relaxng.error_log.last_error
66             message = "%s (line %s)" % (error.message, error.line)
67             raise InvalidRSpec(message)
68         return True
69         
70
71     def __str__(self):
72         return self.toxml()
73
74     def toxml(self):
75         return self.header + etree.tostring(self.xml, pretty_print=True)  
76         
77     def save(self, filename):
78         f = open(filename, 'w')
79         f.write(self.toxml())
80         f.close()
81  
82 if __name__ == '__main__':
83     rspec = RSpec()
84     print rspec