source: fedd/federation/topdl.py @ cdb62d9

axis_examplecompt_changesinfo-opsversion-2.00version-3.01version-3.02
Last change on this file since cdb62d9 was cdb62d9, checked in by Ted Faber <faber@…>, 15 years ago

add computer name & rate info, small tweaks

  • Property mode set to 100644
File size: 9.4 KB
Line 
1#!/usr/local/bin/python
2
3class base:
4    @staticmethod
5    def init_class(c, arg):
6        if isinstance(arg, dict):
7            return c(**arg)
8        elif isinstance(arg, c):
9            return arg
10        else:
11            return None
12
13    @staticmethod
14    def make_list(a):
15        if isinstance(a, basestring) or isinstance(a, dict): return [ a ]
16        elif getattr(a, '__iter__', None): return a
17        else: return [ a ]
18
19
20
21class ConsistencyError(RuntimeError): pass
22
23class Attribute(base):
24    def __init__(self, attribute, value):
25        self.attribute = attribute
26        self.value = value
27
28    def to_dict(self):
29        return { 'attribute': self.attribute, 'value': self.value }
30
31class Capacity(base):
32    def __init__(self, rate, kind):
33        self.rate = rate
34        self.kind = kind
35
36    def to_dict(self):
37        return { 'rate': self.rate, 'kind': self.kind }
38
39class Latency(base):
40    def __init__(self, time, kind):
41        self.time = time
42        self.kind = kind
43
44    def to_dict(self):
45        return { 'time': self.time, 'kind': self.kind }
46
47class Substrate(base):
48    def __init__(self, name, capacity=None, latency=None, attribute=[]):
49        self.name = name
50        self.capacity = self.init_class(Capacity, capacity)
51        self.latency = self.init_class(Latency, latency)
52        self.attribute = [ self.init_class(Attribute, a) \
53                for a in self.make_list(attribute) ]
54        self.interfaces = [ ]
55
56    def to_dict(self):
57        rv = { 'name': self.name }
58        if self.capacity:
59            rv['capacity'] = self.capacity.to_dict()
60        if self.latency:
61            rv['latency'] = self.latency.to_dict()
62        if self.attribute:
63            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
64        return rv
65
66class CPU(base):
67    def __init__(self, type, attribute=[]):
68        self.type = type
69        self.attribute = [ self.init_class(Attribute, a) for a in \
70                self.make_list(attribute) ]
71
72    def to_dict(self):
73        rv = { 'type': self.type}
74        if self.attribute:
75            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
76        return rv
77
78class Storage(base):
79    def __init__(self, amount, persistence, attribute=[]):
80        if isinstance(amount, basestring):
81            self.amount = float(amount)
82        else:
83            self.amount = amount
84        self.presistence = persistence
85        self.attribute = [ self.init_class(Attribute, a) \
86                for a in self.make_list(attribute) ]
87
88    def to_dict(self):
89        rv = { 'amount': float(self.amount), 'persistence': self.persistence }
90        if self.attribute:
91            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
92        return rv
93
94class OperatingSystem(base):
95    def __init__(self, name, version=None, distribution=None,
96            distributionversion=None, attribute=[]):
97        self.name = name
98        self.version = version
99        self.distribution = distribution
100        self.distributionversion = distributionversion
101        self.attribute = [ self.init_class(Attribute, a) \
102                for a in self.make_list(attribute) ]
103
104    def to_dict(self):
105        rv = { 'name': self.name }
106        if self.version: rv['version'] = self.version
107        if self.distribution: rv['version'] = self.distribution
108        if self.distributionversion: rv['version'] = self.distributionversion
109        if self.attribute:
110            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
111        return rv
112
113class Software(base):
114    def __init__(self, location, install=None, attribute=[]):
115        self.location = location
116        self.install = install
117        self.attribute = [ self.init_class(Attribute, a)\
118                for a in self.make_list(attribute) ]
119
120    def to_dict(self):
121        rv = { 'location': self.location }
122        if self.install: rv['install'] = self.install
123        if self.attribute:
124            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
125        return rv
126
127class Interface(base):
128    def __init__(self, substrate, capacity=None, latency=None, attribute=[],
129            element=None):
130        self.substrate = self.make_list(substrate)
131        self.capacity = self.init_class(Capacity, capacity)
132        self.latency = self.init_class(Latency, latency)
133        self.attribute = [ self.init_class(Attribute, a) \
134                for a in self.make_list(attribute) ]
135        self.element = element
136        self.subs = [ ]
137
138    def to_dict(self):
139        rv = { 'substrate': self.substrate }
140        if self.capacity:
141            rv['capacity'] = self.capacity.to_dict()
142        if self.latency:
143            rv['latency'] = self.latency.to_dict()
144        if self.attribute:
145            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
146        return rv
147
148class Computer(base):
149    def __init__(self, name=[], cpu=[], os=[], software=[], storage=[],
150            interface=[], attribute=[]):
151        def assign_element(i):
152            i.element = self
153
154        self.name = self.make_list(name)
155        self.cpu = [ self.init_class(CPU, c)  for c in self.make_list(cpu) ]
156        self.os = [ self.init_class(OperatingSystem, c) \
157                for c in self.make_list(os) ]
158        self.software = [ self.init_class(Software, c) \
159                for c in self.make_list(software) ]
160        self.storage = [ self.init_class(Storage, c) \
161                for c in self.make_list(storage) ]
162        self.interface = [ self.init_class(Interface, c) \
163                for c in self.make_list(interface) ]
164        self.attribute = [ self.init_class(Attribute, a) \
165                for a in self.make_list(attribute) ]
166        map(assign_element, self.interface)
167
168    def to_dict(self):
169        rv = { }
170        if self.cpu:
171            rv['cpu'] = [ c.to_dict() for  c in self.cpu ]
172        if self.os:
173            rv['os'] = [ o.to_dict() for o in self.os ]
174        if self.software:
175            rv['software'] = [ s.to_dict() for s in self.software ]
176        if self.storage:
177            rv['storage'] = [ s.to_dict for s in self.storage ]
178        if self.interface:
179            rv['interface'] = [ i.to_dict() for i in self.interface ]
180        if self.attribute:
181            rv['attribute'] = [ i.to_dict() for i in self.attribute ]
182        return { 'computer': rv }
183
184class Other(base):
185    def __init__(self, interface=[], attribute=[]):
186        self.interface = [ self.init_class(Interface, c) \
187                for c in self.make_list(interface) ]
188        self.attribute = [ self.init_class(Attribute, c) \
189                for c in self.make_list(attribute) ]
190
191    def to_dict(self):
192        if self.interface:
193            rv['interface'] = [ i.to_dict() for i in self.interface ]
194        if self.attribute:
195            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
196
197
198class Topology(base):
199    @staticmethod
200    def init_element(e):
201        """
202        e should be of the form { typename: args } where args is a dict full of
203        the right parameters to initialize the element.  e should have only one
204        key, but we walk e's keys in an arbitrary order and instantiate the
205        first key we know how to.
206        """
207        classmap = {
208                'computer': Computer,
209                'other': Other,
210            }
211
212        for k in e.keys():
213            cl = classmap.get(k, None)
214            if cl: return cl(**e[k])
215
216    def __init__(self, substrates=[], elements=[]):
217        self.substrates = [ self.init_class(Substrate, s) \
218                for s in self.make_list(substrates) ]
219        self.elements = [ self.init_element(e) \
220                for e in self.make_list(elements) ]
221        # Could to this init in one gulp, but we want to look for duplicate
222        # substrate names
223        substrate_map = { }
224        for s in self.substrates:
225            if not substrate_map.has_key(s.name):
226                substrate_map[s.name] = s
227            else:
228                raise ConsistencyError("Duplicate substrate name %s" % s.name)
229
230        substrate_map = dict([ (s.name, s) for s in self.substrates ])
231        for e in self.elements:
232            for i in e.interface:
233                for sn in i.substrate:
234                    # NB, interfaces have substrate names in their substrate
235                    # attribute.
236                    if substrate_map.has_key(sn):
237                        sub = substrate_map[sn]
238                        i.subs.append(sub)
239                        sub.interfaces.append(i)
240                    else:
241                        raise ConsistencyError("No such substrate for %s" % sn)
242
243    def to_dict(self):
244        rv = { }
245        if self.substrates:
246            rv['substrates'] = [ s.to_dict() for s in self.substrates ]
247        if self.elements:
248            rv['elements'] = [ s.to_dict() for s in self.elements ]
249        return rv
250
251def topology_from_xml(file=None, top="topology"):
252    import xml.parsers.expat
253
254    class parser:
255        def __init__(self):
256            self.stack = [ ]
257            self.chars = ""
258            self.key = ""
259            self.have_chars = False
260            self.current = { }
261            self.in_cdata = False
262       
263        def start_element(self, name, attrs):
264            self.chars = ""
265            self.have_chars = False
266            self.key = str(name)
267            self.stack.append((self.current, self.key))
268            self.current = { }
269
270        def end_element(self, name):
271            if self.have_chars:
272                self.chars = self.chars.strip()
273                if len(self.chars) >0:
274                    addit = self.chars
275                else:
276                    addit = self.current
277            else:
278                addit = self.current
279
280            parent, key = self.stack.pop()
281            if parent.has_key(key):
282                if isinstance(parent[key], list):
283                    parent[key].append(addit)
284                else:
285                    parent[key] = [parent[key], addit]
286            else:
287                parent[key] = addit
288            self.current = parent
289            self.key = key
290
291            self.chars = ""
292            self.have_chars = False
293
294        def char_data(self, data):
295            self.have_chars = True
296            self.chars += data
297
298    p = parser()
299    xp = xml.parsers.expat.ParserCreate()
300
301    xp.StartElementHandler = p.start_element
302    xp.EndElementHandler = p.end_element
303    xp.CharacterDataHandler = p.char_data
304
305    f = open(file, "r")
306
307    xp.ParseFile(f)
308
309    return Topology(**p.current[top])
310
311def topology_to_xml(t, top=None):
312    """
313    Print the topology as XML.  This is quick and dirty, but should work for
314    many purposes.  Convert the topology to a dict and print it recursively.
315    """
316    from xml.sax.saxutils import escape
317
318    def dict_to_xml(e, top=None):
319        if top: rv = "<%s>" % top
320        else: rv = ""
321
322        for k in e.keys():
323            if isinstance(e[k], (basestring, int, float, long)):
324                rv += "<%s>%s</%s>" % (k, escape(e[k]), k)
325            elif isinstance(e[k], dict):
326                rv += "<%s>%s</%s>" % (k, dict_to_xml(e[k]), k)
327            elif getattr(e[k], '__iter__', None):
328                for ee in e[k]:
329                    if isinstance(ee, dict):
330                        rv += "<%s>%s</%s>" % (k, dict_to_xml(ee), k)
331                    else:
332                        rv += "<%s>%s</%s>" % (k, escape(ee), k)
333            else:
334                raise ConsistencyError("What is this?? %s %s" % (k, e[k]))
335        if top: rv += "</%s>" % top
336        return rv
337
338    return dict_to_xml(t.to_dict(), top)
339
340
341
Note: See TracBrowser for help on using the repository browser.