Not celebrating the holidays does give me something: free time during break.
I've been tinkering with a whole bunch of different things leisurely during my break thus far. Before leaving, I had attended RIT's STEM Challenge hackathon (didn't end up working on a STEM game, though) and decided with my buddy Logan Mitchell that we'd try porting a MUD engine I had written some time ago in Java to Python, and make it better. It would be a good side-project to learn some things about the language.
One of the notable cool things I picked up was a nice way of generating the common "help files" for commands in the MUD, in a way that allows allowed us to document these commands at the same time. I had an idea. What if we could use the function docstring, and through reflection, generate a helpfile from it? Turns out, python can make that happen pretty easily. Inside our commands.py module...
import sys
import inspect
...
def help(args):
"""
Check the helpfiles for something.
syntax: help <subject>
subject - the subject or command which you want to check for help on
"""
...
# args is a namedtuple
helpFunctionName = args.tokens[1]
# use reflection to get a list of this module's function object
functions = inspect.getmembers(sys.modules[__name__], inspect.isfunction)
for functionName, function in functions:
if functionName == helpFunctionName:
docstring = function.__doc__
prelude = "help file for: " + args.tokens[1] + "\n"
dashline = ("-"*len(prelude))
return prelude + dashline + docstring
So, calling "help help" in our MUD will actually pull out help's docstring and have it contribute to the help file. Pretty cool stuff.
Saturday, December 24, 2011
Monday, December 12, 2011
Dorrie part II
I did some more stuff with Dorrie last week.
Beyond some aesthetics changes, I improved the usability of Dorrie through tooltips and previews. This led to a bunch of fun with the well-known jQuery Tools tooltip library. Using the library to create nice looking tooltips was pretty simple, once things got set up. It just boils down importing the library (and make sure that you import it after the general jQuery library), and setting up the function call inside the document ready clause like so:
$("match").tooltip();
This will call the default tooltip aesthetic, pulling in the text from the matched element's title field. Of course, this is the easiest scenario. Getting things just right to match the aesthetics of the site required a lot of tweaking.
On the home page of Dorrie, I list the steps that the process will take you through for creating your remix. After some feedback, I was told that these steps should have their terms defined, so this was a pretty good place to start for adding these tooltips. The code ended up looking like this:
$("#steps a[title]").tooltip({ effect: 'fade', tipClass: 'tooltipBig'});
The jQuery library allows the user to define multiple parameters for these tooltips. The most important, I found, were the effect, tipClass, and position parameters. The effect parameter defines the particular animation the tooltip uses upon popup (There are default styles, which are quite nice, but the library supports the ability to create custom animations, too). The tipClass parameter points to the css that the tooltip will use (allowing you to have multiple styles and not rely on the "tooltip" css class). Position defines the position where the tooltip will pop up.
In my fork of the Dorrie project, I added a few different styles of tooltips. Each one had their own respective bubble images that needed adjusting (all of mine derive from the free-to-use minimalist images jQuery tools provides), and positioning that needed tweaking.
One of the more interesting areas of using these tooltips is in the /packages/ step. Here, I add tooltips for package categories by pulling in the data that Dorrie uses in the backend making use of Django's Mako support:
<a href="#" title="{{cat.description}}">{{ cat.name }}</a>
These <a> tags make up categories that the jQuery accordion widget uses. The title fields are pulled in from the python backend (packages.py) data, a collection of python objects that represent categories, groups, and individual packages. This data is initialized on service startup. This data is in turn pulled in from Fedora's huge comps file that defines the packages it has. Overall, pretty nifty. Unfortunately, the way Dorrie currently pulls in the list of package groups within a category is different from the way it handles categories. Instead of bringing in a list of package groups that use the backend group model, it's just a list of strings. I'm not sure why it's done this way, and I intend to change it soon.
I also made an attempt to take control of jQuery Tools tooltip's way of embedding HTML in a tooltip so that I could create some nice tooltip image previews of the desktop environments. Using mako's loops, the html for each group was displayed, and inside of that it was easy to create a simple condition for adding in the tooltip...
{% for cat in cats %}
<h4><a href="#" title="{{cat.description}}">{{ cat.name }}</a></h4>
<div>
{% for group in cat.groups %}
<input type="checkbox" id="grp_{{ group }}" value="{{ group }}"
onClick='someOnclickFunction("{{ group }}")' />
{% ifequal cat.name "Desktop Environments" %}
Add CSS class for tooltip matching
Create HTML div for a tooltip
{% else %}
Default Behavior
{% endifequal %}
<br />
{% endfor %}
</div>
{% endfor %}
There were some problems, however. The html loaded inside the tooltip is by default the next section. This led us with two problems.
If we defined the HTML inside the loop, it would be generated multiple times - once per group - and could generate content based on the backend model, with data pulled in using mako. This would be fine, except that Mako generates the html before the jQuery library checks for the html to snag for the tooltip. This results in the first div being pulled out for the tooltip, and the rest displaying outside any tooltip. Not what we wanted. If I were to pull out the tooltip div from the loop, and create an explicit reference to it, the content would not be dynamic, as it would not have been generated within the loop.
I quickly looked for an alternative solution for a simple tooltip image preview, and stumbled across Alen Grakalic's script over at CSSGlobe, which does the trick pretty much flawless. I used his code as a base and am adjusting it to work for my solution (I have to finish and make the image position dynamic based on the page, not mouse position).
I'll be sure to post again when I get some of these things working, to detail other changes I've made.
Beyond some aesthetics changes, I improved the usability of Dorrie through tooltips and previews. This led to a bunch of fun with the well-known jQuery Tools tooltip library. Using the library to create nice looking tooltips was pretty simple, once things got set up. It just boils down importing the library (and make sure that you import it after the general jQuery library), and setting up the function call inside the document ready clause like so:
$("match").tooltip();
This will call the default tooltip aesthetic, pulling in the text from the matched element's title field. Of course, this is the easiest scenario. Getting things just right to match the aesthetics of the site required a lot of tweaking.
On the home page of Dorrie, I list the steps that the process will take you through for creating your remix. After some feedback, I was told that these steps should have their terms defined, so this was a pretty good place to start for adding these tooltips. The code ended up looking like this:
$("#steps a[title]").tooltip({ effect: 'fade', tipClass: 'tooltipBig'});
The jQuery library allows the user to define multiple parameters for these tooltips. The most important, I found, were the effect, tipClass, and position parameters. The effect parameter defines the particular animation the tooltip uses upon popup (There are default styles, which are quite nice, but the library supports the ability to create custom animations, too). The tipClass parameter points to the css that the tooltip will use (allowing you to have multiple styles and not rely on the "tooltip" css class). Position defines the position where the tooltip will pop up.
In my fork of the Dorrie project, I added a few different styles of tooltips. Each one had their own respective bubble images that needed adjusting (all of mine derive from the free-to-use minimalist images jQuery tools provides), and positioning that needed tweaking.
One of the more interesting areas of using these tooltips is in the /packages/ step. Here, I add tooltips for package categories by pulling in the data that Dorrie uses in the backend making use of Django's Mako support:
<a href="#" title="{{cat.description}}">{{ cat.name }}</a>
These <a> tags make up categories that the jQuery accordion widget uses. The title fields are pulled in from the python backend (packages.py) data, a collection of python objects that represent categories, groups, and individual packages. This data is initialized on service startup. This data is in turn pulled in from Fedora's huge comps file that defines the packages it has. Overall, pretty nifty. Unfortunately, the way Dorrie currently pulls in the list of package groups within a category is different from the way it handles categories. Instead of bringing in a list of package groups that use the backend group model, it's just a list of strings. I'm not sure why it's done this way, and I intend to change it soon.
I also made an attempt to take control of jQuery Tools tooltip's way of embedding HTML in a tooltip so that I could create some nice tooltip image previews of the desktop environments. Using mako's loops, the html for each group was displayed, and inside of that it was easy to create a simple condition for adding in the tooltip...
{% for cat in cats %}
<h4><a href="#" title="{{cat.description}}">{{ cat.name }}</a></h4>
<div>
{% for group in cat.groups %}
<input type="checkbox" id="grp_{{ group }}" value="{{ group }}"
onClick='someOnclickFunction("{{ group }}")' />
{% ifequal cat.name "Desktop Environments" %}
Add CSS class for tooltip matching
Create HTML div for a tooltip
{% else %}
Default Behavior
{% endifequal %}
<br />
{% endfor %}
</div>
{% endfor %}
There were some problems, however. The html loaded inside the tooltip is by default the next section. This led us with two problems.
If we defined the HTML inside the loop, it would be generated multiple times - once per group - and could generate content based on the backend model, with data pulled in using mako. This would be fine, except that Mako generates the html before the jQuery library checks for the html to snag for the tooltip. This results in the first div being pulled out for the tooltip, and the rest displaying outside any tooltip. Not what we wanted. If I were to pull out the tooltip div from the loop, and create an explicit reference to it, the content would not be dynamic, as it would not have been generated within the loop.
I quickly looked for an alternative solution for a simple tooltip image preview, and stumbled across Alen Grakalic's script over at CSSGlobe, which does the trick pretty much flawless. I used his code as a base and am adjusting it to work for my solution (I have to finish and make the image position dynamic based on the page, not mouse position).
I'll be sure to post again when I get some of these things working, to detail other changes I've made.
Wednesday, November 9, 2011
Dorrie
So after abandoning my misadventures of last week, I decided to clone the Dorrie project, and use that as the underlying base for the remixerator. The bread and butter of this project is in the pykickstart.parser module, which has many tools to parsing and generating a working kickstart file. I will briefly explain the key functions and objects that are used in dorrie.
pykickstart.parser defines three classes:
KickstartParser - a state machine used when going through a kickstart
Packages - an object that encapsulates all the selected (and removed) packages of the kickstart.
Script - an object that encapsulates a script of the kickstart file.
The KickstartParser's most useful function for us is the readKickstart() function. This, given a kickstart file, will go through (using the state machine internally) and create all the objects necessary to represent a particular kickstart. This uses internal parsing and handling functions. It also has an internal handler object that saves and executes commands that are parsed.
The Packages object has four important lists. The lists excludedList and packageList, that contain the actual packages for the kickstart (the former being denoted with a '-' character). The lists groupList and excludedGroupList are also included in this module. Essentially, when we want to add or remove any particular package, we add the package name to the respective lists.
The Script module has two important fields: script and type. Each script object should encapsulate only one script, the script field set to the actual script's string, and the type set to the relevant type found in pykickstart.constants. Creating a script object is not difficult, however, adding it in, is. Pykickstart has a BaseHandler object (to which KickstartParser's handler object is a subclass), that contains a scripts section, holding these instances of the script object.
One of the difficulties in using the dorrie project for the remixerator is that adding a post script is non-trivial. The documentation states that to add a script, you call KickstartParser.addScript... but this function actually doesn't exist. For the time being, one way to get around this is to literally append %post script to the returned formatted string. I did this for the sake of time, but this will be changed when I can find a more proper way to add a script object.
After this, I had to go through Dorrie's settings.py file and change references to reflect fedora 16. This included versions of the internal parser (these are defined in the latest pykickstart repository), and package trees.
Next is a little bit of de-chroming, to get the aesthetics looking like an RIT project.
Edit: Scripts get added when the Script "section" object has its finalize method called. I'll post more on this later.
pykickstart.parser defines three classes:
KickstartParser - a state machine used when going through a kickstart
Packages - an object that encapsulates all the selected (and removed) packages of the kickstart.
Script - an object that encapsulates a script of the kickstart file.
The KickstartParser's most useful function for us is the readKickstart() function. This, given a kickstart file, will go through (using the state machine internally) and create all the objects necessary to represent a particular kickstart. This uses internal parsing and handling functions. It also has an internal handler object that saves and executes commands that are parsed.
The Packages object has four important lists. The lists excludedList and packageList, that contain the actual packages for the kickstart (the former being denoted with a '-' character). The lists groupList and excludedGroupList are also included in this module. Essentially, when we want to add or remove any particular package, we add the package name to the respective lists.
The Script module has two important fields: script and type. Each script object should encapsulate only one script, the script field set to the actual script's string, and the type set to the relevant type found in pykickstart.constants. Creating a script object is not difficult, however, adding it in, is. Pykickstart has a BaseHandler object (to which KickstartParser's handler object is a subclass), that contains a scripts section, holding these instances of the script object.
One of the difficulties in using the dorrie project for the remixerator is that adding a post script is non-trivial. The documentation states that to add a script, you call KickstartParser.addScript... but this function actually doesn't exist. For the time being, one way to get around this is to literally append %post script to the returned formatted string. I did this for the sake of time, but this will be changed when I can find a more proper way to add a script object.
After this, I had to go through Dorrie's settings.py file and change references to reflect fedora 16. This included versions of the internal parser (these are defined in the latest pykickstart repository), and package trees.
Next is a little bit of de-chroming, to get the aesthetics looking like an RIT project.
Edit: Scripts get added when the Script "section" object has its finalize method called. I'll post more on this later.
Thursday, November 3, 2011
HTML and JQuery forms on Twisted
When I started to prototype a remixerator, I created a simple form front-end using simple html and JQuery.
Here's the head. I used this nice css theme generator to get an aesthetic that worked, put in a few of my own tweaks, and imported the necessary JQuery files. In my particular form, I liked the idea of having "sections" as tabs, and "subsections" represented by the accordion layout. When using accordions inside tabs, make sure to bring in accordions FIRST and tabs SECOND or else they won't render correctly.
<head>
<title>Remixerator Prototype</title>
<link type="text/css" href="css/custom-theme/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
<link type="text/css" href="css/overall.css" rel="stylesheet"/>
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
<script type="text/javascript">
$(function(){
// Accordion
$("#accordion").accordion({ header: "h3" });
// Tabs
$('#tabs').tabs();
$("#RemixPostForm").submit(function(e){
console.log("Entering Submit");
$.post('http://localhost:8080/handler.html', function(data) {
console.log("Entering Submit Callback");
});
});
});
</script>
</head>
Now for the body. Tabs are represented as a list with ids, and each tab's content is a div with a matching id. Otherwise, this is pretty standard html form stuff. I spent [too much] of my time dealing with css issues with this form.
<body>
<form id="RemixPostForm">
<!-- Tabs -->
<h2 class="demoHeaders">Remixerator</h2>
<div id="tabs">
<ul>
<li><a href="#tabs-wall">Wallpaper</a></li>
<li><a href="#tabs-apps">Applications</a></li>
<li><a href="#tabs-create">Create</a></li>
</ul>
<div id="tabs-wall">
<h3>First, select your wallpaper.</h3>
<div id="wallpaper_table" align = "center">
<table id="imagegrid" border="0" width="400">
<tr>
<td align="center"><img src="images/ritwallpaper.jpg" alt="gallery thumbnail" height = "80" width = "120"/></td>
<td align="center"><img src="images/f15wallpaper.png" alt="gallery thumbnail" height = "80" width = "120"/></td>
</tr>
<tr>
<td align="center"><input type="radio" name="ritwallpaper_cb" id="ritwallpaper_cb" checked="checked"/></td>
<td align="center"><input type="radio" name="f15wallpaper_cb" id="f15wallpaper_cb"/></td>
</tr>
</table>
</div>
</div>
<div id="tabs-apps">
<h3>Next, choose the applications you want.</h3>
<div id="accordion">
<div>
<h3><a href="#">Office and Text</a></h3>
<div>
<input type="checkbox" name="vim_cb" id="vim_cb"/>Vim<br>
<input type="checkbox" name="emacs_cb" id="emacs_cb"/>Emacs<br>
<input type="checkbox" name="nano_cb" id="nano_cb"/>Nano<br>
<input type="checkbox" name="libre_cb" id="libre_cb"/>Libreoffice<br>
</div>
</div>
<div>
<h3><a href="#">Video, Images, and Music</a></h3>
<div>
<input type="checkbox" name="inkscape_cb" id="inkscape_cb"/>Inkscape<br>
<input type="checkbox" name="gimp_cb" id="gimp_cb"/>Gimp<br>
<input type="checkbox" name="dia_cb" id="dia_cb"/>Dia<br>
<input type="checkbox" name="banshee_cb" id="banshee_cb"/>Banshee<br>
</div>
</div>
<div>
<h3><a href="#">Communication and Internet</a></h3>
<div>
<input type="checkbox" name="firefox_cb" id="firefox_cb"/>Firefox<br>
<input type="checkbox" name="elinks_cb" id="elinks_cb"/>ELinks<br>
<input type="checkbox" name="midori_cb" id="midori_cb"/>Midori<br>
<input type="checkbox" name="pidgin_cb" id="pidgin_cb"/>Pidgin<br>
</div>
</div>
<div>
<h3><a href="#">Utility</a></h3>
<div>
<input type="checkbox" name="zsh_cb" id="zsh_cb"/>Z-Shell<br>
<input type="checkbox" name="git_cb" id="git_cb"/>Git<br>
<input type="checkbox" name="htop_cb" id="htop_cb"/>Htop<br>
<input type="checkbox" name="powertop_cb" id="powertop_cb"/>Powertop<br>
<input type="checkbox" name="screen_cb" id="screen_cb"/>Screen<br>
<input type="checkbox" name="wine_cb" id="wine_cb"/>Wine<br>
</div>
</div>
<div>
<h3><a href="#">Fun and Games</a></h3>
<div>
<input type="checkbox" name="nethack_cb" id="nethack_cb"/>Nethack<br>
</div>
</div>
</div>
</div>
<div id="tabs-create">
<h3>Now click the button below to start making your remix.</h3>
<input type="submit" value="Go!" name="start_button" id="start_button" />
</div>
</div>
</form>
</body>
Lastly, the twisted bits. I simply created a simple service, server.py, which hosted the form, and had the handler.
Here's the head. I used this nice css theme generator to get an aesthetic that worked, put in a few of my own tweaks, and imported the necessary JQuery files. In my particular form, I liked the idea of having "sections" as tabs, and "subsections" represented by the accordion layout. When using accordions inside tabs, make sure to bring in accordions FIRST and tabs SECOND or else they won't render correctly.
<head>
<title>Remixerator Prototype</title>
<link type="text/css" href="css/custom-theme/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
<link type="text/css" href="css/overall.css" rel="stylesheet"/>
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
<script type="text/javascript">
$(function(){
// Accordion
$("#accordion").accordion({ header: "h3" });
// Tabs
$('#tabs').tabs();
$("#RemixPostForm").submit(function(e){
console.log("Entering Submit");
$.post('http://localhost:8080/handler.html', function(data) {
console.log("Entering Submit Callback");
});
});
});
</script>
</head>
Now for the body. Tabs are represented as a list with ids, and each tab's content is a div with a matching id. Otherwise, this is pretty standard html form stuff. I spent [too much] of my time dealing with css issues with this form.
<body>
<form id="RemixPostForm">
<!-- Tabs -->
<h2 class="demoHeaders">Remixerator</h2>
<div id="tabs">
<ul>
<li><a href="#tabs-wall">Wallpaper</a></li>
<li><a href="#tabs-apps">Applications</a></li>
<li><a href="#tabs-create">Create</a></li>
</ul>
<div id="tabs-wall">
<h3>First, select your wallpaper.</h3>
<div id="wallpaper_table" align = "center">
<table id="imagegrid" border="0" width="400">
<tr>
<td align="center"><img src="images/ritwallpaper.jpg" alt="gallery thumbnail" height = "80" width = "120"/></td>
<td align="center"><img src="images/f15wallpaper.png" alt="gallery thumbnail" height = "80" width = "120"/></td>
</tr>
<tr>
<td align="center"><input type="radio" name="ritwallpaper_cb" id="ritwallpaper_cb" checked="checked"/></td>
<td align="center"><input type="radio" name="f15wallpaper_cb" id="f15wallpaper_cb"/></td>
</tr>
</table>
</div>
</div>
<div id="tabs-apps">
<h3>Next, choose the applications you want.</h3>
<div id="accordion">
<div>
<h3><a href="#">Office and Text</a></h3>
<div>
<input type="checkbox" name="vim_cb" id="vim_cb"/>Vim<br>
<input type="checkbox" name="emacs_cb" id="emacs_cb"/>Emacs<br>
<input type="checkbox" name="nano_cb" id="nano_cb"/>Nano<br>
<input type="checkbox" name="libre_cb" id="libre_cb"/>Libreoffice<br>
</div>
</div>
<div>
<h3><a href="#">Video, Images, and Music</a></h3>
<div>
<input type="checkbox" name="inkscape_cb" id="inkscape_cb"/>Inkscape<br>
<input type="checkbox" name="gimp_cb" id="gimp_cb"/>Gimp<br>
<input type="checkbox" name="dia_cb" id="dia_cb"/>Dia<br>
<input type="checkbox" name="banshee_cb" id="banshee_cb"/>Banshee<br>
</div>
</div>
<div>
<h3><a href="#">Communication and Internet</a></h3>
<div>
<input type="checkbox" name="firefox_cb" id="firefox_cb"/>Firefox<br>
<input type="checkbox" name="elinks_cb" id="elinks_cb"/>ELinks<br>
<input type="checkbox" name="midori_cb" id="midori_cb"/>Midori<br>
<input type="checkbox" name="pidgin_cb" id="pidgin_cb"/>Pidgin<br>
</div>
</div>
<div>
<h3><a href="#">Utility</a></h3>
<div>
<input type="checkbox" name="zsh_cb" id="zsh_cb"/>Z-Shell<br>
<input type="checkbox" name="git_cb" id="git_cb"/>Git<br>
<input type="checkbox" name="htop_cb" id="htop_cb"/>Htop<br>
<input type="checkbox" name="powertop_cb" id="powertop_cb"/>Powertop<br>
<input type="checkbox" name="screen_cb" id="screen_cb"/>Screen<br>
<input type="checkbox" name="wine_cb" id="wine_cb"/>Wine<br>
</div>
</div>
<div>
<h3><a href="#">Fun and Games</a></h3>
<div>
<input type="checkbox" name="nethack_cb" id="nethack_cb"/>Nethack<br>
</div>
</div>
</div>
</div>
<div id="tabs-create">
<h3>Now click the button below to start making your remix.</h3>
<input type="submit" value="Go!" name="start_button" id="start_button" />
</div>
</div>
</form>
</body>
Lastly, the twisted bits. I simply created a simple service, server.py, which hosted the form, and had the handler.
from twisted.web import static, http, resource, server
from twisted.web.server import Site
from twisted.web.static import File
from twisted.internet import reactor
from twisted.web.resource import Resource
import cgi
import sys
class FormPage(Resource):
isLeaf = True
allowedMethods = ('GET', 'POST')
def __init__(self):
resource.Resource.__init__(self)
def render_GET(self, request):
return self.render_POST(request)
def render_POST(self, request):
#Modify Kickstart, do validation
return '<html><body>ISO Created!</body></html>'
if __name__ == "__main__":
root = static.File('/Users/eitanromanoff/Documents/github/Remixerator')
indexPage = Resource()
formHandler = FormPage()
root.putChild('index.html', indexPage)
root.putChild('handler.html', formHandler)
reactor.listenTCP(8080, server.Site(root))
reactor.run()
The Remixerator
I've been working on a new project as of late that uses the kickstart tinkering I did at the start of the quarter, and takes it a step further. The goal is to create a "remixerator" - an interface, ideally a web-based one, that allows a user to create a custom fedora remix (that is still RIT-themed in content and aesthetics). The end goal would be to put it into a machine similar to the kiosk, and have a very controlled and automated process for taking in a DVD, customizing the remix, and then burning the image for a user.
The customization of the remix is easy enough - it's just a generation of a kickstart. All of my custom scripting that was done can still be injected into the kickstart, what really changes is the configuration of applications. To start, I looked into various existing technologies that do similar things.
LiveUSB creator was not really relevant to what I was trying to do.
SuseStudio was very similar, but based on several cloud technologies that are not necessary to my project at hand. Furthermore, our RIT remixes were to run Fedora.
Kickstarter was too much targeted towards Meego.
And there were several other applications as well.
While I was no eager to re-invent the wheel, none of the above projects really fit the bill. Ultimately, I decided that all I would have to do is make a web form (perhaps take the opportunity to learn some JQuery), generate a kickstart on submit, run the creation process, and serve up a webpage when it was finished.
The form was easy enough, just a bunch of html and JQuery running on twisted. Hosting things on twisted was pretty simple, too, to get started. However, things quickly became less trivial. Launching the script on a post was simple, but being able to constantly update a page, given the output of the create livecd process, would be difficult to tackle, and it was hard to believe there was another tool available that did some of this for me.
Looking again the other day, I stumbled across the dorrie project, which does much of what I wanted to do. It also has a convenient spot in its parser where I could likely inject the postscript sections that I wrote for the RIT remix. I'll take this approach from here on out, and bother with aesthetics later.
The customization of the remix is easy enough - it's just a generation of a kickstart. All of my custom scripting that was done can still be injected into the kickstart, what really changes is the configuration of applications. To start, I looked into various existing technologies that do similar things.
LiveUSB creator was not really relevant to what I was trying to do.
SuseStudio was very similar, but based on several cloud technologies that are not necessary to my project at hand. Furthermore, our RIT remixes were to run Fedora.
Kickstarter was too much targeted towards Meego.
And there were several other applications as well.
While I was no eager to re-invent the wheel, none of the above projects really fit the bill. Ultimately, I decided that all I would have to do is make a web form (perhaps take the opportunity to learn some JQuery), generate a kickstart on submit, run the creation process, and serve up a webpage when it was finished.
The form was easy enough, just a bunch of html and JQuery running on twisted. Hosting things on twisted was pretty simple, too, to get started. However, things quickly became less trivial. Launching the script on a post was simple, but being able to constantly update a page, given the output of the create livecd process, would be difficult to tackle, and it was hard to believe there was another tool available that did some of this for me.
Looking again the other day, I stumbled across the dorrie project, which does much of what I wanted to do. It also has a convenient spot in its parser where I could likely inject the postscript sections that I wrote for the RIT remix. I'll take this approach from here on out, and bother with aesthetics later.
Monday, October 24, 2011
So many things!
I did a lot last week.
The next version of the Kiosk code is up on my github now. I cleaned things up to the point where customizing it is easy thanks to configparser. Why have I never seen this library before?
Here's a sample configuration file.
And here's the python code to parse it.
The next version of the Kiosk code is up on my github now. I cleaned things up to the point where customizing it is easy thanks to configparser. Why have I never seen this library before?
Here's a sample configuration file.
# Kiosk Settings
# cycler settings...
[kiosk_cycler]
# location of where to toss things
file_location = /Users/fossrit/Desktop
# host to ping to test for a working internet connection
ping_host = www.google.com
# number of times to retry a connection. -1 for unending attempts
ping_counter = 3
# number of seconds to wait in between ping attempts
ping_timer = 30
# list of hosts for the feeds. Follows the format:
# host : /location
# candidate feeds are delimited by commas.
feed_hosts = foss.rit.edu : /files/bookmarks.rss, cs.rit.edu : /~ear7631/feed.rss
And here's the python code to parse it.
parser = SafeConfigParser()
parser.read('kiosk_config')
file_location = parser.get('kiosk_cycler', 'file_location')
ping_host = parser.get('kiosk_cycler', 'ping_host')
ping_counter = int(parser.get('kiosk_cycler', 'ping_counter'))
ping_timer = int(parser.get('kiosk_cycler', 'ping_timer'))
feed_hosts_dirty = parser.get('kiosk_cycler', 'feed_hosts')
Easy, isn't it? I was also messing around with wxWoof, too, and finally got around to tinkering with wxPython a bit more. You can look at the full code here, but I really just wanted to share how easy adding drag-and-drop functionality is. My goal was to make a button that, not only brought up a file selection if clicked, but had file recognized drag-and-drop implemented as well. All that really needs to be done is hook up a FileDropTarget to your container, which handles the magic.
self.boxButton.SetDropTarget(self.dropTarget)
self.dropTarget = FileDropTarget(self.boxButton)
After that it's just a matter of hooking up the OnDropFiles function your FileDropTarget.
I've now started working with html5 forms, jquery, and the twisted web framework, so there will be posts on my experiences with these in the coming days.
I've now started working with html5 forms, jquery, and the twisted web framework, so there will be posts on my experiences with these in the coming days.
Monday, October 10, 2011
Making a Simple Kiosk - Part II
The Kiosk has come a long way. A few hours of sanding, some clean up, a lot of rust removal, primer, a coat of black paint, some adventurous logo painting (which didn't work out), stencils, and posters later, I give you, the completed project. Minus a lock. Ours was too short.
Here's the front.
And the side.
Don't forget the guts.
Here's the front.
And the side.
Don't forget the guts.
Wednesday, October 5, 2011
Making a simple Kiosk
Today, a very different sort of project managed to find its way to me. I've been tasked with building a kiosk out of this, this, and last but not least, this. It's a pretty cool idea - make the mini run, mount the monitor, cover it with plexiglass, sand the box, and give it a nice new coat of paint. My parents had always made sure that power tools were more than an arm's length from me at all times, so I've grown up with zero experience in that realm. Needless to say, I started with the mac.
The box needed to do only one task: start up, open a browser, cycle through links. Perfect job for applescript. The script to launch a browser and loop through links is simple:
The box needed to do only one task: start up, open a browser, cycle through links. Perfect job for applescript. The script to launch a browser and loop through links is simple:
#!/usr/bin/osascript
-- argv is a list of links to loop through
on run argv
tell application "Opera.app" to activate
tell application "System Events"
tell process "Opera"
click menu item "New Window" of menu "File" of menu bar 1
end tell
end tell
-- list of urls to cycle
repeat
repeat with someurl in argv
tell application "System Events" to set browserRunning to (name of processes) contains "Opera"
if browserRunning then
else
exit repeat
end if
tell application "Opera.app"
set URL of document 1 to someurl
delay 5
end tell
end repeat
tell application "System Events" to set browserRunning to (name of processes) contains "Opera"
if browserRunning then
else
exit repeat
end if
end repeat
end run
I made a python script that does everything else. Grabs a list of links from a feed, passes them over to the cycler:
#!/usr/bin/env python
import feedparser
import os
from subprocess import call
# this actually parses the feed as if it uses the firefox live bookmarks format
# your parsing may change on how your links are represented
applecmd = []
applecmd.append("osascript")
applecmd.append("kioskcycle.scpt")
d = feedparser.parse("http://myhost.com/somefeed.rss")
bookmarkitems = d['items']
for item in bookmarkitems:
for link in item.links:
applecmd.append(link.href)
os.chdir("/Users/someuser/Desktop")
call(applecmd)
And got it all working by turning my python script into a natively built python applet, and telling OSX to use it as a startup item. All pretty straight forward, under normal circumstances. Of course, my script initially used Safari, but things can never be that simple. RIT is its own Certification Authority, and Safari thinks some of RIT's sites (ie, my.rit.edu) are traps. Even if you forcefully allow the certificate to pass, Safari will warn you. This got on my nerves, so I went looking for another browser. Firefox dropped support for PPC a long time ago. Chrome never had it. TenFourFox, as nice as that is, doesn't work with applescript. I decided to settle on Opera 10, the last Opera release to work with PPC. It also gained Applescript support since 9.5. Nice.
I've got some major sanding, painting, drilling, and polishing to do tomorrow, so I'll be sure to post a picture of the final product of my labor. Mmmmm... power tools.
Monday, October 3, 2011
Combating selinux for the timeline
That timeline that was being worked on ended up being hosted on foss.rit.edu, but getting it there took nothing less than an arduous battle with selinux. I first created an alias so that I could put all my work in a single directory on a separate user account on the box, and tossed it into the right /etc/httpd/conf.d/ configuration file.
Any work from here on out could be tossed in /home/myusraccount/timeline/. While this is convenient, this posed a slight problem. The form I had created to give me an easy way to add events to my timeline posts its information to be handled by my python cgi script. This script gets effectively run as the "apache" user, and selinux has a slight problem allowing the apache user modify files inside /home/myusraccount/timeline.
First I changed the owner of the relevant file and the timeline directory file to the apache user. No luck.
I then tried to add apache and myusraccount to the same group, giving the group full permissions of the file and directory being touched by the cgi script. No luck.
For random kicks, I turned off selinux. That did the trick. Turning it back on, I tried to change the context of the files and directories myself, but couldn't get anything to work for the life of me. My mentors in the fossbox showed me a nifty tool, audit2allow, which allows users to generate allow rulesets for specific operations. This tool parses the logs for denied permissions messages, and can automatically generate exceptions to them. Basically do what you want to do, watch it fail, run audit2allow, and apply a rule. Of course, you'll want to be careful with the rule you do apply, since selinux could very well be protecting your machine from a big security risk.
Alias /timeline "/home/myusraccount/timeline"
AllowOverride All
Options Indexes
order allow,deny
Allow from all
Any work from here on out could be tossed in /home/myusraccount/timeline/. While this is convenient, this posed a slight problem. The form I had created to give me an easy way to add events to my timeline posts its information to be handled by my python cgi script. This script gets effectively run as the "apache" user, and selinux has a slight problem allowing the apache user modify files inside /home/myusraccount/timeline.
First I changed the owner of the relevant file and the timeline directory file to the apache user. No luck.
I then tried to add apache and myusraccount to the same group, giving the group full permissions of the file and directory being touched by the cgi script. No luck.
For random kicks, I turned off selinux. That did the trick. Turning it back on, I tried to change the context of the files and directories myself, but couldn't get anything to work for the life of me. My mentors in the fossbox showed me a nifty tool, audit2allow, which allows users to generate allow rulesets for specific operations. This tool parses the logs for denied permissions messages, and can automatically generate exceptions to them. Basically do what you want to do, watch it fail, run audit2allow, and apply a rule. Of course, you'll want to be careful with the rule you do apply, since selinux could very well be protecting your machine from a big security risk.
Tuesday, September 27, 2011
RIT Remix Hosting and Interactive Timeline
The spin remix is now hosted. Thank you Ralph Bean for tossing that up! I hope that I'll have a chance to tinker with it in the future and make some improvements to it later. For now, there's a different task at hand.
One of the key things that is missing from the FOSS Box @ RIT is a slick timeline that can show the world what we've been up to - something that's polished and comprehensive. Remy Decausemaker's forked version of MIT's Simile Exhibit project fit the bill perfectly. The project uses a whole bunch of javascript magic to render its visuals, but at its source, generates its content from a single contributors file.
Adding entries to the timeline is trivial. It's just a matter of going from this and this to a series of formatted entries:
Not a difficult process, but a time-consuming one. One that I'm not so willing to do in the future, so I decided to create a pretty simply html form that would let me enter entires. The form is simple HTML and creates a little something like this. After creating the form, I whipped up a simple CGI script in python, which has a module that makes form handling easy. Lastly, this form launches a simple script that appends entries to the contributor.js file.
This should save a lot of hassle in the future. Of course, I wasn't able to host this simple web service on my CS webspace, given the restricted permissions that disallowed me to create any sort of .htaccess file without a headache. Gives me a good opportunity to check out openshift which has been getting a lot of buzz lately.
One of the key things that is missing from the FOSS Box @ RIT is a slick timeline that can show the world what we've been up to - something that's polished and comprehensive. Remy Decausemaker's forked version of MIT's Simile Exhibit project fit the bill perfectly. The project uses a whole bunch of javascript magic to render its visuals, but at its source, generates its content from a single contributors file.
Adding entries to the timeline is trivial. It's just a matter of going from this and this to a series of formatted entries:
{ "type" : "Event",
"label" : "ImagineRIT 2010",
"discipline" : "Event",
"date" : "2010-05-01",
"relationship" : "Event",
"relationship-detail" : "ImagineRIT 2010",
"imageURL" : "Event.png",
"url" : "http://www.rit.edu/imagine/"
},
Not a difficult process, but a time-consuming one. One that I'm not so willing to do in the future, so I decided to create a pretty simply html form that would let me enter entires. The form is simple HTML and creates a little something like this. After creating the form, I whipped up a simple CGI script in python, which has a module that makes form handling easy. Lastly, this form launches a simple script that appends entries to the contributor.js file.
This should save a lot of hassle in the future. Of course, I wasn't able to host this simple web service on my CS webspace, given the restricted permissions that disallowed me to create any sort of .htaccess file without a headache. Gives me a good opportunity to check out openshift which has been getting a lot of buzz lately.
Tuesday, September 20, 2011
wxWoof
Rochester's getting colder. Autumn is here. I like that.
This past Saturday was the big Software Freedom event. I had a few people ask me about the spin, grab copies, so I pointed them to the public repo and showed them what went on in creating it (my previous post was editing for some more details regarding the process). It was good fun. And so was the hackathon. I didn't really go in with any particular project in mind, so I decided to get started on working on something that I've been meaning to work on for quite some time.
Ever hear of woof?
It's a nifty python (2.7) script that turns your computer into a single-file distribution server. Or, should you want, archive directories for you, and host the archive. It's pretty simple, but really useful. Need to toss a file over on your other box, and don't have a USB drive with you? No problem, just run the script on the file. By default, the script hosts it on port 8080. All you need to do to grab the file is open up your browser of choice, and connect at the host's ip (displayed if you don't know off hand), and selected port. Easy. (If you want -really- impressive speeds, try sharing a network connection from the host, and connecting the two via ethernet. That's some nice file transfer speeds.)
Some of my friends saw me using it, and really loved the script, but aren't familiar with the command line at all, or even the concept of a directory path. The script could also use a little python 3 makeover. So, I took the opportunity to start looking into some gui libraries to put a simple front-end on the script.
There were a few options. If you can recall, I already messed around with pygtk2, which was very simple and powerful. It is, however, getting it to work in OSX 10.5 and later is annoying. I then looked into something more current and robust, and stumbled upon PyQt, based on the mammoth Qt framework by Nokia. In the end I decided to just use the tried and true wxPython libraries.
This wasn't without it's issues, either, though, as wxPython hasn't been updated to work properly with Python 64 bit installs. I actually had to create a little launcher that appropriately ran my ui correctly. This was accomplished by using the following script:
You can check out my very simple gui at the public repo if you're interested. Right now, I got something that works, but I'll continue to add to and improve the UI (as well as clean up the script) over time and post more about it in the near future. Chances are I'll take a look at wxDesigner and wxGlade.
This past Saturday was the big Software Freedom event. I had a few people ask me about the spin, grab copies, so I pointed them to the public repo and showed them what went on in creating it (my previous post was editing for some more details regarding the process). It was good fun. And so was the hackathon. I didn't really go in with any particular project in mind, so I decided to get started on working on something that I've been meaning to work on for quite some time.
Ever hear of woof?
It's a nifty python (2.7) script that turns your computer into a single-file distribution server. Or, should you want, archive directories for you, and host the archive. It's pretty simple, but really useful. Need to toss a file over on your other box, and don't have a USB drive with you? No problem, just run the script on the file. By default, the script hosts it on port 8080. All you need to do to grab the file is open up your browser of choice, and connect at the host's ip (displayed if you don't know off hand), and selected port. Easy. (If you want -really- impressive speeds, try sharing a network connection from the host, and connecting the two via ethernet. That's some nice file transfer speeds.)
Some of my friends saw me using it, and really loved the script, but aren't familiar with the command line at all, or even the concept of a directory path. The script could also use a little python 3 makeover. So, I took the opportunity to start looking into some gui libraries to put a simple front-end on the script.
There were a few options. If you can recall, I already messed around with pygtk2, which was very simple and powerful. It is, however, getting it to work in OSX 10.5 and later is annoying. I then looked into something more current and robust, and stumbled upon PyQt, based on the mammoth Qt framework by Nokia. In the end I decided to just use the tried and true wxPython libraries.
This wasn't without it's issues, either, though, as wxPython hasn't been updated to work properly with Python 64 bit installs. I actually had to create a little launcher that appropriately ran my ui correctly. This was accomplished by using the following script:
#! /usr/bin/env python
import subprocess
subprocess.call(["arch", "-i386", "python", "window.py"])
You can check out my very simple gui at the public repo if you're interested. Right now, I got something that works, but I'll continue to add to and improve the UI (as well as clean up the script) over time and post more about it in the near future. Chances are I'll take a look at wxDesigner and wxGlade.
Wednesday, September 14, 2011
Creating a Fedora RIT Spin
The full process.
Up until now, I've only given snippets of the steps it took to create an RIT Live CD Spin of Fedora 15, so this time I'll detail every step (and issue) I took along the way, along with some of the issues I ran into. To start, there are Live CD creation tools provided to you for creating Fedora Live CDs that are pretty much automated, but setting up the configuration of the Live CD is what can be tricky. Before we can really begin, we need to install the tools needed for creating our spin. You can get these tools by grabbing the following packages.
Next, we need our own kickstart file. We can start with a basic kickstart file as shown below.
This is pretty much the most basic of kickstart files that can be used. These kickstart files effectively define how the Live CD will be created, and are the tool you use for customizing your spin. First, the
The next step is defining the applications you want in your spin. Add every desired package in the
Because the creation process creates a filesystem to be put on a non-rewritable media, it's important to get all your customization done in the kickstart file. There is a useful area of the file, the
To tackle the bookmarks, I had to poke around a bit at the guts of Firefox 6 to see how bookmarks are stored. When firefox runs, it creates a default profile for the user, and stores bookmarks in an
Firefox 6 contains an archive called
Lastly, I had to change the default wallpaper for the spin. The first step to getting this to work was to get the wallpapers on the newly created filesystem (before
Instead, I decided to write a script that safely tuck away the default Fedora 15 backgrounds (there are three versions of it), and swap in my own wallpapers for them. It's a bit hackish, but at least the wallpaper will appear on the the default startup, and this way, I don't have to create a whole new package and tinker with the various
Something to note as well is that Fedora 15 has 3 default wallpapers, each with different resolutions that reside in their own folders. It's a good idea to do the same with your own.
A last feature I wished to add to the spin is a prompt to ask if the user would like to run the live cd with RPM Fusion enabled. Obviously, much of the software out there that provides a user with a normal experience is proprietary, and won't be put on the spin by default. Instead, the user should have the ability to quickly fetch and enable these packages.
I created a simple pygtk2 launcher that runs a simple fetch script for RPM Fusion (Note, the prior is a python script, and the latter is a fetch script, so simply rename the extension if you pull them from my public webspace). Adding scripts to the startup routine is trivial... if you have access to the gsettings command. My first approach was to add my script to init.d, but this approach will not work. A second approach I took was to attempt to pull a customized bash_profile which launches the prompt on login, and tosses it into the user folder. However, this will not work either, because the liveusr profile will not be created at the time of %post, and therefore, it is not possible to modify its bash_profile. This feature will require a little more exploration.
Given more time for refinement, a better approach would be to make a proper package for the wallpapers, but if you have to get it done quickly (and with the long creation process), this quick-and-dirty method should get things set just fine. Overall, however, the process is fairly straight forward, and most of the difficulties come from the fact that you don't have too much wiggle room on the temporary filesystem customization.
The final kickstart file I use for the RIT spin can be found here. If you wish to contribute to the spin project, or make your own based on what I have, feel free to fork the public repo.
Up until now, I've only given snippets of the steps it took to create an RIT Live CD Spin of Fedora 15, so this time I'll detail every step (and issue) I took along the way, along with some of the issues I ran into. To start, there are Live CD creation tools provided to you for creating Fedora Live CDs that are pretty much automated, but setting up the configuration of the Live CD is what can be tricky. Before we can really begin, we need to install the tools needed for creating our spin. You can get these tools by grabbing the following packages.
sudo yum -y install spin-kickstarts livecd-tools
Next, we need our own kickstart file. We can start with a basic kickstart file as shown below.
%include /usr/share/spin-kickstarts/fedora-live-desktop.ks
%include /usr/share/spin-kickstarts/fedora-live-minimization.ks
%packages
%end
%post
%end
This is pretty much the most basic of kickstart files that can be used. These kickstart files effectively define how the Live CD will be created, and are the tool you use for customizing your spin. First, the
%include
statement is used to pull in other made kickstart files. A basic spin can get nearly all of the groundwork done by just pulling in the two kickstart files shown above, provided that you don't mind the default Live CD environment.The next step is defining the applications you want in your spin. Add every desired package in the
%packages section
. For example, no RIT student can live without emacs and pidgin, so I'll toss those packages in.%packages
emacs
pidgin
%end
Because the creation process creates a filesystem to be put on a non-rewritable media, it's important to get all your customization done in the kickstart file. There is a useful area of the file, the
%post
section, that allows you to run commands to customize the environment before the creation process runs mksquashfs
to make things final, stuffing it all into a nice iso package. For the RIT spin, we wanted a few little features, such as having default RIT bookmarks for Firefox, and some nice RIT default wallpaper.To tackle the bookmarks, I had to poke around a bit at the guts of Firefox 6 to see how bookmarks are stored. When firefox runs, it creates a default profile for the user, and stores bookmarks in an
sqlite
database. While it would have been easy to set some bookmarks, and just copy the .sqlite
file for later use, I noticed that Firefox computes a random hash for the user profile folder, making it pretty much impossible to be able to predict the folder of the default profile for any given user. I then looked into how these .sqlite
databases are being generated.Firefox 6 contains an archive called
omni.jar
, located in /usr/lib/firefox-6 that effectively has a bookmarks.html
file inside, defining the bookmarks hierarchy that is used to generate the inital sqlite database for each profile. In order to change this, it is necessary to unzip the archive, swap in the bookmarks.html
file (here's mine), and finally zip it back up. To do this I put my own script into the %post
section of the kickstart file. The script I use to do this can be found here.Lastly, I had to change the default wallpaper for the spin. The first step to getting this to work was to get the wallpapers on the newly created filesystem (before
mksquashfs
runs) to be used. While it's possible to create your own package to include, I decided it might be easier to just look for a swapping command. Because Fedora 15 runs gnome3, it was tempting to use the gsettings
command to set the background, but this won't do anything. (One approach that may work is creating a startup script to do just that, but gsettings
cannot be run without the user being logged in and gnome initialized. Therefore, it won't work in the %post
section of the kickstart file.)Instead, I decided to write a script that safely tuck away the default Fedora 15 backgrounds (there are three versions of it), and swap in my own wallpapers for them. It's a bit hackish, but at least the wallpaper will appear on the the default startup, and this way, I don't have to create a whole new package and tinker with the various
.xml
configuration files to change the default location. Note that wget
is necessary to add as a package to grab the files that I had hosted (probably the easiest way to pull in file needed by the %post
scripts). Furthermore, livecd users are not added to the sudoers file, so it's easiest just to run a su -c "command"
to get the job done, as the background folder contents does require root permissions to alter.Something to note as well is that Fedora 15 has 3 default wallpapers, each with different resolutions that reside in their own folders. It's a good idea to do the same with your own.
A last feature I wished to add to the spin is a prompt to ask if the user would like to run the live cd with RPM Fusion enabled. Obviously, much of the software out there that provides a user with a normal experience is proprietary, and won't be put on the spin by default. Instead, the user should have the ability to quickly fetch and enable these packages.
I created a simple pygtk2 launcher that runs a simple fetch script for RPM Fusion (Note, the prior is a python script, and the latter is a fetch script, so simply rename the extension if you pull them from my public webspace). Adding scripts to the startup routine is trivial... if you have access to the gsettings command. My first approach was to add my script to init.d, but this approach will not work. A second approach I took was to attempt to pull a customized bash_profile which launches the prompt on login, and tosses it into the user folder. However, this will not work either, because the liveusr profile will not be created at the time of %post, and therefore, it is not possible to modify its bash_profile. This feature will require a little more exploration.
Given more time for refinement, a better approach would be to make a proper package for the wallpapers, but if you have to get it done quickly (and with the long creation process), this quick-and-dirty method should get things set just fine. Overall, however, the process is fairly straight forward, and most of the difficulties come from the fact that you don't have too much wiggle room on the temporary filesystem customization.
The final kickstart file I use for the RIT spin can be found here. If you wish to contribute to the spin project, or make your own based on what I have, feel free to fork the public repo.
Monday, September 12, 2011
Setting the Background for a Fedora 15 Remix
If you're creating a Fedora Remix, you might want to give a nice customized desktop wallpaper. This can be done easily using the %post section of the kickstart file.
Firstly, make sure that you go to the directory that houses our own background images.
cd /usr/share/backgrounds/images
Next we want to fetch a background image and bring it into the created filesystem. Note that resolv.config, at the time that the post script executes, is not yet set up, so there's no DNS lookup going on. We need to use the ip. Be sure to also have wget included in the %package section of the kickstart file.
wget --header="Host: www.someplace.com/wherever/your/image/is.jpg" http://123.45.67.89/wherever/your/image/is.jpg
Finally, all that's left is to configure the background image by calling the gsettings command. Previously, in Fedora 14 and previous, you would use gconftool-2 to edit the background image schema, but gnome3 uses a slightly different command:
gsettings set org.gnome.desktop.background picture-uri "file:///usr/share/backgrounds/images/yourimage.jpg"
There are many other settings that can be altered using the gsettings command, so you have a lot of freedom in customizing the look and feel of your Fedora 15 remix.
Firstly, make sure that you go to the directory that houses our own background images.
cd /usr/share/backgrounds/images
Next we want to fetch a background image and bring it into the created filesystem. Note that resolv.config, at the time that the post script executes, is not yet set up, so there's no DNS lookup going on. We need to use the ip. Be sure to also have wget included in the %package section of the kickstart file.
wget --header="Host: www.someplace.com/wherever/your/image/is.jpg" http://123.45.67.89/wherever/your/image/is.jpg
Finally, all that's left is to configure the background image by calling the gsettings command. Previously, in Fedora 14 and previous, you would use gconftool-2 to edit the background image schema, but gnome3 uses a slightly different command:
gsettings set org.gnome.desktop.background picture-uri "file:///usr/share/backgrounds/images/yourimage.jpg"
There are many other settings that can be altered using the gsettings command, so you have a lot of freedom in customizing the look and feel of your Fedora 15 remix.
Thursday, September 8, 2011
Fedora Kickstart Files
The past two days have been interesting, to say the least. Creating a live cd isn't really difficult given that there are many tools to create one for you with ease. What is tricky, is using the post installation scripting that the kickstart files. Since the live cd can only be written to once, and due to the natural limitations on customization of a live cd (which is, in part, the point), all customization has to be done when creating the .iso of the live cd. For example, the kickstart file I'm creating makes use of the post installation segment to change some firefox bookmark defaults. Using these scripts to change the background of your Fedora live cd is possible too, should you wish it. Hopefully today, I'll be able to figure out the post-boot problems my build has.
Monday, September 5, 2011
There is a Box of FOSS at RIT, and I am now inside it.
The calendar is marked: September 17th - Software Freedom Day. All my hours could be spent towards creating the perfect Fedora Spin for Open Source loving RIT students, but instead, VMware fusion is intent on making emulation as difficult as possible. Only after jumping through hoops thought to be long gone, could I finally get the guest OS to recognize that my computer has, in fact, a usb port. Useful. Tomorrow will be a day filled with tinkering as I explore kickstart files, something I've never done before. Hopefully, I can bundle in the right applications that covers most anything a new RIT student needs.
Subscribe to:
Posts (Atom)