1 # Copyright (c) 2009, 2010 Nicira Networks
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
17 from ovs.db import error
19 from ovs.db import types
21 class DbSchema(object):
22 """Schema for an OVSDB database."""
24 def __init__(self, name, tables):
28 # Validate that all ref_tables refer to the names of tables
30 for table in self.tables.itervalues():
31 for column in table.columns.itervalues():
32 self.__check_ref_table(column, column.type.key, "key")
33 self.__check_ref_table(column, column.type.value, "value")
37 parser = ovs.db.parser.Parser(json, "database schema")
38 name = parser.get("name", ['id'])
39 tablesJson = parser.get("tables", [dict])
43 for tableName, tableJson in tablesJson.iteritems():
44 if tableName.startswith('_'):
45 raise error.Error("names beginning with \"_\" are reserved",
47 elif not ovs.db.parser.is_identifier(tableName):
48 raise error.Error("name must be a valid id", json)
49 tables[tableName] = TableSchema.from_json(tableJson, tableName)
51 return DbSchema(name, tables)
55 for table in self.tables.itervalues():
56 tables[table.name] = table.to_json()
57 return {"name": self.name, "tables": tables}
59 def __check_ref_table(self, column, base, base_name):
60 if (base and base.type == types.UuidType and base.ref_table and
61 base.ref_table not in self.tables):
62 raise error.Error("column %s %s refers to undefined table %s"
63 % (column.name, base_name, base.ref_table),
66 class IdlSchema(DbSchema):
67 def __init__(self, name, tables, idlPrefix, idlHeader):
68 DbSchema.__init__(self, name, tables)
69 self.idlPrefix = idlPrefix
70 self.idlHeader = idlHeader
74 parser = ovs.db.parser.Parser(json, "IDL schema")
75 idlPrefix = parser.get("idlPrefix", [unicode])
76 idlHeader = parser.get("idlHeader", [unicode])
79 del subjson["idlPrefix"]
80 del subjson["idlHeader"]
81 schema = DbSchema.from_json(subjson)
83 return IdlSchema(schema.name, schema.tables, idlPrefix, idlHeader)
85 class TableSchema(object):
86 def __init__(self, name, columns, mutable=True, max_rows=sys.maxint):
88 self.columns = columns
89 self.mutable = mutable
90 self.max_rows = max_rows
93 def from_json(json, name):
94 parser = ovs.db.parser.Parser(json, "table schema for table %s" % name)
95 columnsJson = parser.get("columns", [dict])
96 mutable = parser.get_optional("mutable", [bool], True)
97 max_rows = parser.get_optional("maxRows", [int])
101 max_rows = sys.maxint
103 raise error.Error("maxRows must be at least 1", json)
106 raise error.Error("table must have at least one column", json)
109 for columnName, columnJson in columnsJson.iteritems():
110 if columnName.startswith('_'):
111 raise error.Error("names beginning with \"_\" are reserved",
113 elif not ovs.db.parser.is_identifier(columnName):
114 raise error.Error("name must be a valid id", json)
115 columns[columnName] = ColumnSchema.from_json(columnJson,
118 return TableSchema(name, columns, mutable, max_rows)
123 json["mutable"] = False
125 json["columns"] = columns = {}
126 for column in self.columns.itervalues():
127 if not column.name.startswith("_"):
128 columns[column.name] = column.to_json()
130 if self.max_rows != sys.maxint:
131 json["maxRows"] = self.max_rows
135 class ColumnSchema(object):
136 def __init__(self, name, mutable, persistent, type):
138 self.mutable = mutable
139 self.persistent = persistent
143 def from_json(json, name):
144 parser = ovs.db.parser.Parser(json, "schema for column %s" % name)
145 mutable = parser.get_optional("mutable", [bool], True)
146 ephemeral = parser.get_optional("ephemeral", [bool], False)
147 type = types.Type.from_json(parser.get("type", [dict, unicode]))
150 return ColumnSchema(name, mutable, not ephemeral, type)
153 json = {"type": self.type.to_json()}
155 json["mutable"] = False
156 if not self.persistent:
157 json["ephemeral"] = True