Here is a patch to add serializer support for MySQL against the devel
branch.  It is not well tested and, for the moment, I am not running
this patch on my cobbler server.  However, it seems to work in my
limited testing.  You should consider this experimental until proven
otherwise.

It will auto-create tables, but you need to give it a database name of a
pre-existing database and user with permissions with which cobbler can
create tables.

I hope someone will get some use from it.

Sean

---
 cobbler/modules/serializer_mysql.py |  139 +++++++++++++++++++++++++++++++++++
 cobbler/settings.py                 |    5 +
 config/settings                     |   12 +++
 3 files changed, 156 insertions(+), 0 deletions(-)
 create mode 100644 cobbler/modules/serializer_mysql.py

diff --git a/cobbler/modules/serializer_mysql.py b/cobbler/modules/serializer_mysql.py
new file mode 100644
index 0000000..3cad584
--- /dev/null
+++ b/cobbler/modules/serializer_mysql.py
@@ -0,0 +1,139 @@
+"""
+MySQL Serializer code for cobbler
+
+based heavily on the serializer_catalog.py code
+
+"""
+import distutils.sysconfig
+import os
+import sys
+import MySQLdb
+
+from cexceptions import *
+import api as cobbler_api
+
+plib = distutils.sysconfig.get_python_lib()
+mod_path="%s/cobbler" % plib
+sys.path.insert(0, mod_path)
+
+def connect_db(type="master"):
+    capi = cobbler_api.BootAPI()
+    settings = capi.settings() 
+
+    if type == "slave" and settings.mysql_server_slave != "":
+        host = settings.mysql_server_slave
+    else:
+        host = settings.mysql_server
+    try:
+        db = MySQLdb.connect(db=settings.mysql_database, user=settings.mysql_user, host=host)
+    except MySQLdb.Error, e:
+        raise CX("Error %d: %s" % (e.args[0], e.args[1]))
+
+    return db
+
+def register():
+    """
+    The mandatory cobbler module registration hook.
+    """
+    return "serializer"
+
+def create_table_if_not_exists(db, table):
+    """
+    Internal serializer function to create the MySQL table if it doesn't already exist.
+    """
+    c = db.cursor()
+    if not c.execute("SHOW TABLES LIKE '"+table+"'"):
+        c.execute("CREATE TABLE IF NOT EXISTS "+table+" ( name varchar(255) PRIMARY KEY, data TEXT ) Engine=InnoDB")
+
+    return None
+
+def serialize_item(obj, item):
+    db = connect_db()
+    table = obj.collection_type()
+
+    create_table_if_not_exists(db, table)
+    c = db.cursor()
+    datastruct = item.to_datastruct()
+    c.execute("REPLACE INTO "+table+""" (name, data) VALUES (%s, %s)""", (str(item.name), repr(datastruct)))
+    db.commit()
+    db.close()
+    return True
+
+def serialize_delete(obj, item):
+    db = connect_db()
+    table = obj.collection_type()
+    c = db.cursor()
+    c.execute("DELETE FROM "+table+""" WHERE name = %s""", (item.name,))
+    db.commit()
+    db.close()
+    return True
+
+def deserialize_item_raw(collection_type, item_name):
+    db = connect_db("slave")
+    table = obj.collection_type()
+    c = db.cursor()
+
+    try:
+        c.execute("SELECT data FROM "+table+" WHERE name = %s""", (item_name,))
+    except MySQLdb.ProgrammingError:
+        sys.stderr.write("error retrieving row for %s in %s\n" % (item_name, table))
+        db.close()
+        return None
+    row = c.fetchone()
+    datastruct = eval(row[0])
+    db.close()
+    return datastruct
+
+def serialize(obj):
+    """
+    Save an object to the database.  Object must "implement" Serializable.
+    Will create the table if it can.  Returns True on Success,
+    False on permission errors.
+    This should not be used by API if serialize_item is available.
+    """
+
+    for entry in obj:
+        serialize_item(obj, entry)
+    return True
+
+def deserialize_raw(collection_type):
+    datastruct = []
+    db = connect_db("slave")
+    c = db.cursor()
+    try:
+        c.execute("SELECT data FROM "+collection_type)
+    except MySQLdb.ProgrammingError:
+        return []
+    while (1):
+        row = c.fetchone()
+        if row == None:
+            break
+        datastruct.append(eval(row[0]))
+    db.close()
+    return datastruct
+
+def deserialize(obj,topological=False):
+    """
+    Populate an existing object with the contents of datastruct.
+    Object must "implement" Serializable.  
+    """
+
+    datastruct = deserialize_raw(obj.collection_type())
+
+    if topological and type(datastruct) == list:
+       # in order to build the graph links from the flat list, sort by the
+       # depth of items in the graph.  If an object doesn't have a depth, sort it as
+       # if the depth were 0.  It will be assigned a proper depth at serialization
+       # time.  This is a bit cleaner implementation wise than a topological sort,
+       # though that would make a shiny upgrade.
+       datastruct.sort(__depth_cmp)
+    obj.from_datastruct(datastruct)
+    return True
+
+def __depth_cmp(item1, item2):
+    if not item1.has_key("depth"):
+       return 1
+    if not item2.has_key("depth"):
+       return -1
+    return cmp(item1["depth"],item2["depth"])
+
diff --git a/cobbler/settings.py b/cobbler/settings.py
index 527b3dc..66158ef 100644
--- a/cobbler/settings.py
+++ b/cobbler/settings.py
@@ -61,6 +61,11 @@ DEFAULTS = {
     "manage_dns"                  : 0,
     "manage_forward_zones"        : [],
     "manage_reverse_zones"        : [],
+    "mysql_database"              : 'cobbler',
+    "mysql_password"              : '',
+    "mysql_server"                : 'localhost',
+    "mysql_server_slave"          : '',
+    "mysql_user"                  : 'cobbler',
     "named_conf"                  : "/etc/named.conf",
     "next_server"                 : "127.0.0.1",
     "omapi_enabled"		  : 0,
diff --git a/config/settings b/config/settings
index d48e2f4..190aec6 100644
--- a/config/settings
+++ b/config/settings
@@ -94,6 +94,18 @@ manage_dns: 0
 manage_forward_zones: []
 manage_reverse_zones: []
 
+# if using serializer_mysql to store objects, you can set the MySQL DB
+# configuration parameters here.  You can ignore this if you are not
+# using "serializer_mysql"
+# If you set "mysql_server_slave" to something other than '', cobbler will
+# query that MySQL server for all SELECTs and send updates to mysql_server.
+# You can use that to support a master->slave replication environment.
+mysql_server: 'localhost'
+mysql_server_slave: ''
+mysql_database: 'cobbler'
+mysql_user: 'cobbler'
+mysql_password: ''
+
 # if using cobbler with manage_dhcp, put the IP address
 # of the cobbler server here so that PXE booting guests can find it
 # if you do not set this correctly, this will be manifested in TFTP open timeouts.
-- 
1.5.5.1

_______________________________________________
cobbler mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/cobbler

Reply via email to