~romaimperator/keryx/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
""" Keryx library """

# Imports
import logging
import os.path
import platform
import socket
import re
import sys

# Append libkeryx to path so anything can use it's modules
sys.path.append(os.path.dirname(__file__))
import urlgrabber

try:
    from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
    from sqlalchemy.orm import sessionmaker, relation, backref
    from sqlalchemy.ext.declarative import declarative_base
except:
    logging.error('SQLAlchemy is not installed. Visit www.sqlalchemy.org to ' \
                  'get the latest version.')
    sys.exit(1)

# Library metadata
__appname__ = 'libkeryx'
__version__ = '1.0.0'
__date__    = '2009-06-15'
__author__  = 'Chris Oliver <excid3@gmail.com>, Buran Ayuthia <the.ayuthias@gmail.com>'
__url__     = 'http://keryxproject.org'

definitions = []

Base = declarative_base()


class Definition:
    """Never should be instanciated itself"""
    def __init__(self, project, db_filename):
        # Create the project directores if they do not exist

        # Set the project to be used for other methods in
        # this class
        self.project = project

        # Create the directory to store the downloads.  Downloads
        # for all projects will be stored in the same folder to 
        # prevent multiple downloads of the same file
        self.downloads_dir = 'downloads/'
        #if not os.path.exists(self.downloads_dir):
        #    os.mkdir(self.downloads_dir)

        # Set the database filename
        sql_filename = 'sqlite:///' + db_filename

        # Create engine
        self.engine = create_engine(sql_filename)

        # global application scope.  create Session class, engine
        Session = sessionmaker()

        # connect to the database
        self.connection = self.engine.connect()

        # bind an individual Session to the connection
        self.session = Session(bind=self.connection)
        
        # create all the tables
        Base.metadata.create_all(self.engine)
        
        # Create the database tables
        logging.info("Initializing shared database tables...")

        # Call the overridden function of the actual definition
        self.on_init(self.project)


    def __del__(self):
        """Definition destructor
        
        Commits all changes and closes database connection
        """
        self.session.commit()
        self.session.close()


    def on_init(self, project):
        """Should be overridden in definition"""
        pass


    def create(self):
        """Create a new Keryx database"""
        # Query to see if project exists already
        found = self.session.query(Project).filter(Project.name==self.project).all()
        
        if found:
            logging.error("Project already exists")
            return False

        logging.info("Creating project...")
        try:
            self.on_create()
        except Exception, e:
            logging.error(e)


    def on_create(self):
        """Should be overridden in definition"""
        pass


    def update_internet(self):
        """Should be overridden in definition"""
        pass


# These are the mapper classes to help access the database easier.
# Only define the tables that are generic to all definitions not 
# the definition-specific ones.
class Project(Base):
    """Table for storing projects"""
    __tablename__ = "projects"
    
    id = Column(Integer, primary_key=True)
    name = Column(String)
    architecture = Column(String)
    hostname = Column(String)
    definition = Column(String)
    version = Column(String)
  
  
    def __init__(self, name, architecture, hostname, definition, version):
        self.name = name
        self.architecture = architecture
        self.hostname = hostname
        self.definition = definition
        self.version = version

    
    def __repr__(self):
        return "<Project('%s','%s','%s','%s','%s')>" % (self.name, 
            self.architecture, self.hostname, self.definition, self.version)


###################
# Functions
###################

def _initialize():
    """ Initializes OS definitions """
    global definitions
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 
                        'definitions')
    sys.path.append(path) # Append the path so that we can import from it
    files = os.listdir(path)
    test = re.compile('', re.IGNORECASE)
    files = filter(test.search, files)
    filenameToModuleName = lambda f: os.path.splitext(f)[0]
    moduleNames = map(filenameToModuleName, files)
    definitions = map(__import__, moduleNames)
    logging.debug("Loaded %i definitions" % len(definitions))

def get_definition(project, db_filename):
    """ Finds the correct definition based on the currrent OS or file """
    # TODO: Make this dynamic
    # Check the "keryx" table for the definition name and version
    # Then load accordingly.
    # For now we are going to hardcode this to load dpkg definitions
    
    # TODO: Read the definition_version string from the file (if exists)
    # If it does, compare versions with the __supports__ using
    # getattr(definitions[0], '__supports__')
    return getattr(definitions[0], definitions[0].__name__)(project, db_filename)


#############
# Entry point
#############
_initialize()