mmorsi's blog
Google Summer of Fedora/Aeolus/Ruby
Submitted by mmorsi on Tue, 2012-05-08 12:07
As some of you may know, Fedora was recently accepted, as a participating organization into the Google Summer of Code. Shortly after this was announced, Buddhika (our Fedora GSoC Admin and Coordinator) circulated a RFC for projects to improve the Fedora distribution as part of this effort. I submitted a few proposals to mentor myself, and am pleased to say there quite a bit of interest by various students, a few of which are now officially working on the various topics.
Specifically Samridh Srinath will be working on improving the Aeolus user experience on Fedora, implementing various aspect of the command line interface and core API features needed to drive it, and Zuhao Wan will be working on a site to highlight and promote the Fedora / Ruby experience, providing a simple one-stop-shop to query for Ruby related packages in Fedora and to assist in the migration process.
Unfortunately, not all of the students who applied were able to be accepted into the GSoC due to the limited number of slots we had available. Both Nitesh Narayan and Furhan Shabir are talented students who submitted strong proposals to work on Aeolus but weren't able to secure the official sponsorship. That being said, both have graciously volunteered to donate some time to assist with the project for which I would like to thank them greatly for.
All in all, I'm looking forward to working with these talented students over the course of the summer and beyond. Stay tuned for more updates as the projects progress and the proposals are implemented.
Until next time, happy hacking!
JSON-RPC Presentation - Brno Ruby Users Group - 26.04.2012
Submitted by mmorsi on Sun, 2012-05-06 10:11
On the Thursday before last I gave a presentation on the JSON-RPC protocol and my implementation of it to the Brno Ruby Users Group. You may find the slides here as well some code examples in Ruby and Javascript here.
RJR is a simple implementation of the JSON-RPC 2.0 standard, using eventmachine on the backend to serve JSON-RPC requests over a multitude of transport types including amqp, http, websockets, tcp/udp, and more. It permits method handlers to be registered and then invoked via any transport the end-user wishes (and the server admin permits access to).
The context of the request is made available to the handler when it is invoked, so that the developer can manage flow control accordingly and store any additional metadata in the requests and responses to extend the JSON-RPC protocol in any manner they desire.
The source code is freely available on github, any patches/issues/etc would be more than welcome. Happy hacking!
Brno Trip Update
Submitted by mmorsi on Mon, 2012-04-30 06:03How I've been busy in the past few weeks. Between working, sightseeing, and plenty of other activities, I've had no chance till now to sit down and write some content for the blog. Now that I'm approaching the 1/2 way point of my trip, I have to say I've had a phenominal time so far, my European collegues at Red Hat are a group of extremely talented guys who are also very fun to work and hang out with. I'm enjoying my stay in the Czech Republic, the people are friendly, there is plenty to do, and overall a pleasant experience. So far my trip over the last few weeks looked like (hover over the images for descriptions, to view full size right click and select 'view image'):
- April 3rd/4th: Flight from Syracuse to Newark, NJ to Copenhagen, Denmark to Prague, CZ; Caught the train from Prague to Brno (overall about ~24hrs worth of traveling)

- Met my coworker Tomas at the Brno train station (he's been a momumental help with the entire trip, a very friendly person and extremely talented engineer). Moved into my apartment here


- Thu/Fri April 5th/6th: Started working out of the Brno office, met all the other Aeolus and Ruby developers working out of here (all around the same age as me, another +), found my way around town including using the public transports and grocery shopping

- My first weekend I explored Brno on foot, I saw the historic old town, the Špilberk castle, the Cathedral of St. Peter and Paul, and got a general feel for the area. Brno is a great city, a good size, not too large that it feels crowded, but not too small that there is nothing todo. It is a university town though, so lots of students, but has plenty of great places to hang out, grab a bite or drink, or do various activities


- The following week primarily consisted of work (it's refreshing to be back in an office working w/ my collegues in person), and attending Aikido class with my collegues Tomas and Petr, both who regularily go. The Sensai here is a city cop that focuses on practical self defense which is different than the more theoretical appoach Sensai Mehter teaches back in Syracuse. Both are good to practice, though I still prefer the dojo back home.
- This week, we also celebrated Red Hat's Billion Dollar Bash in the Brno office. The facilities here arrainged a very fun scavenger hunt around the city, which culminated at the Brno Museum of Technology right by the RH office. The party there was great, lots of great food and treats, and was good to meet developers and other RH employees working on all sorts of projects @ the company.
- I also visited the Brno Hackerspace, Base48 this week, which a few of my collegues are members of. It was great seeing yet another Hackerspace in person, and we all shared plenty of stories of our experiences so far. It seems like they're running into many of the same issues we had w/ the SIG, and I assume many others have had worldwide but overall are doing great and working on some cool projects.
- Was thinking about going to Prague or Vienna on the weekend of the 14th, but ended up just hanging out and relaxing w/ my co-workers after the long week. When I book my flight back from Europe, I'm planning on booking a hotel in Prague for a few days to check out that city.
- The next week was more work, on Wed 4/18 I decided to swing a last minute trip to Amsterdam in the Netherlands. I left via overnight train on the night of the 19th and arrived the morning of Friday 4/20/12. Stayed until Sunday evening when I caught another overnight train back (had reserved a bed in a couchette both ways). The whole experience was remarkable, Amsterdam truly is a magical city; a melting-pot of European cultures, there is a happy and laid back atmosphere in the air, and a "clock-work" feel to the city (think of those old antique clocks w/ lots of moving gears). There is just so much to see and do (I suggest exploring it on foot), between the canals and city parks, to the museums, to the restaurants, coffee-shops, and nightlife, Amsterdam has it all, and overall based on first impressions of the big cities I visited, Amsterdam takes the cake. I stayed in a hostel Friday and Saturday nights which was an interesting experience, the people I ended up staying with were all really friendly and nothing sketchy or bad happend, but I'm not sure if I'd want to do it again (similarily while I got lots of sleep on the train, it was a weird feeling having other passengers come and go from the cabin I was staying in in the middle of the night when I was sleeping). Unfortunately Amsterdam is a touristy city though, things are expensive and there are lots of tourist attractions (at several points I noticed a stark constast between the old and the new worlds, like a modern carnival which was operating in the plaze of one of the cities biggest / oldest churches). Also when you get down to it, it is a big city, which I can't ever see myself permenatly living in (I tend to prefer smaller cities, and areas with lots of nature and large state parks within a very short distance). All in all though, the weekend in Amsterdam was a great time, and I would eagerly jump at the opportuninty to visit again






- On Monday of last week the team went go-karting which was a blast followed by ribs and beer :-) One of the best things about the Czech republic is how inexpensive everything is (that is to an American visitor), a good stack of ribs won't cost you more that $6 or $7 USD, tips included. Also a pint of good beer will only run you a dollar or two. Life is good in the Czech republic :-)


- On the following Wednesday, my UK collegue left to fly back home, so saw him off before working. Had a great time hanging out with Martyn over the last few weeks, and it's good to put a face and memories behind an IRC handle. Work in general has been great, have been getting alot done both on the Aeolus and Ruby/Fedora side of things as well as on my side projects. There have been some exciting updates to everything I've been working on, I've pushed new additions to Snap, have been working with a few students on now-accepted proposals for the Google Summer of Code (which I am now a mentor of, more on this in the near future), have been learning a great deal as far as security and hardening a Rails application is concerned, and am putting a presentation together for the Brno Ruby Users Group (on JSON-RPC and my RJR project), and much more. Look for more details on alot of these in the near future
- Also went rock climbing for the first time since high school on Thursday with some co-workers. Was a fun time and a great workout, a good whole body excercise (especially the upper body and shoulders). I'm looking forward to going again and perhaps trying to find a place back in Syracuse that I frequent and improve my technique
- Furthmore I went for a long bike ride around the Brno Lake and Reservoir and then Slacklining nearby on Sunday with the same co-workers. All in all we ended up biking around 35 Kilometes, and saw Veveří Castle in the process, and while our initial attempts on the Slackline weren't all that successful, it was all a great workout and plenty of fun. Definitely more activities that I'm looking forward to doing again when I get the chance (quite possibly this week! :-) ).

All in all so far the trip has been a blast, I've met so many interesting people from many different places. From my collegues who come from all over Europe (the Czech Republic, Slovakia, Hungary, Italy, Russia, the UK, and more), to random people at all the various places I've visited / stayed at, people are genuently friendly and helpful and always willing to swap stories with a foreigner. There are places right out of the movies and yet places which seem unique in their own right and unlike anywhere else. I'm looking forward to the rest of my stay. Besides Prague, I'd like to visit at least one other European city and/or take in some of the country side (I was thinking about renting a car and just driving around the a bit).
Stay tuned for more updates coming soon! Until then, Chow!
Working from Brno, CZ (04/12 - 06/12)
Submitted by mmorsi on Sun, 2012-03-18 17:56
Starting next month I will be spending some time working onsite w/ my teammates at Redhat Brno in the Czech Republic. This will be my first trip to Europe and I am fully looking forward to going, not only have the previous times I spent working from the office (Raleigh, Boston, NYC) been great networking experiences, but this will be the furthest of my more recent adventures yet (I did visit Egypt on a few occasions during my youth) and I am looking forward to seeing the new culture first hand. During this trip I will be renting an apartment with fellow teammate Martyn from the UK who will also be visiting during the month of April.
I am also planning on visiting a few other cities during my stay, including Prague, Vienna, and Amsterdam. If anyone wants me to bring them back any souvenirs, just ask! And make sure to stay tuned for more updates!
GTK Programming w/ Python
Submitted by mmorsi on Sat, 2012-03-03 17:55
This Wednesday, I will be giving a talk at the March Syracuse Linux Users Group meeting on Programming GTK interfaces w/ PyGTK (along w/ Glade and GOBject Introspection). You can find my presentation here, which I made with showoff (source here, more on this in a subsequent blogpost) and is probably my most ahem interesting presentation to this date (at least I like to think so ;-) ).
As far as the $topic matter itself, cross-platform GUI development has never been easier due to a few simple tools. GTK is available on many platforms, and using Glade you can easily whip up an interface that suites your needs. Wiring up event handlers and the backend code is a cinch due to the gobject bindings which gtk provides that we are able to leverage from a Python app.

Along w/ the presentation I'm planning on giving a quick demo on how to perform these steps, creating a simple Desktop based twitter client. You can download the glade xml file here and the python app itself (also see below). Simply run it with $ python syrlug_demo.py but note you will need to have the python twitter library installed (# sudo yum install python-twitter on Fedora).

Of course this is just the beginning, you can easily expand the interface by editing the XML in Glade and adding new event handlers to the Python script to do whatever you would like.
import os import time import threading import twitter from gi.repository import Gtk, Gdk, GObject INPUT_TEXT='twitter username' GLADE_FILE = os.path.join(os.path.dirname( __file__ ), 'layout.glade') # A worker thread to get twitter data class WorkerThread(threading.Thread): terminate = False twitter_username = None twitter_text = '' def set_buffer(self, buffer): self.buffer = buffer def run(self): while(not self.terminate): api = twitter.Api() self.twitter_text = '' if self.twitter_username != None: try: for status in api.GetUserTimeline(self.twitter_username): self.twitter_text += status.text + "\n" except: pass Gdk.threads_enter() self.buffer.set_text(self.twitter_text) Gdk.threads_leave() time.sleep(5) # The Main Window class SyrlugDemoWindow: def __init__(self): self.builder = Gtk.Builder() self.builder.add_objects_from_file(GLADE_FILE, ["syrlug_demo", "twitter_username", "twitter_text"]) self.window = self.builder.get_object("syrlug_demo") self.username_input = self.builder.get_object("twitter_username") self.username_input.set_text(INPUT_TEXT) self.worker = WorkerThread() self.worker.set_buffer(self.builder.get_object("twitter_text").get_buffer()); self.worker.start() self.builder.connect_signals(self) self.window.connect("destroy", self.close_window) self.window.show() def close_window(self, widget): self.worker.terminate = True Gtk.main_quit() def subscribe_button_clicked(self, widget): input_text = self.username_input.get_text() if input_text != INPUT_TEXT and input_text != "": self.worker.twitter_username = input_text def twitter_username_focus_in(self, widget, param): if widget.get_text() == INPUT_TEXT: widget.set_text("") #widget.set_visibility(False) def twitter_username_focus_out(self, widget, param): if widget.get_text() == "": widget.set_text(INPUT_TEXT) #widget.set_visibility(True) if __name__ == "__main__": # initialize window win = SyrlugDemoWindow() # start gtk loop Gdk.threads_init() GObject.threads_init() Gdk.threads_enter() Gtk.main() Gdk.threads_leave()
Now lets see some of those GTK apps!
Updated Puppet Web Resource Module
Submitted by mmorsi on Wed, 2012-02-29 16:31Some of you may recall the Puppet Web Resource type and provider which I wrote for Aeolus a while back. The module has since undergone alot of improvment from various contributers, and was finally accepted and uploaded to the Puppet module forge. You may download it from there and simply drop it into your puppet module load path to access the resource in all its glory!
Some additional features since I last shared this include
- support for http basic auth,
- cookies support,
- extended request invokation conditions (eg 'only invoke request if <condition> is true' and 'invoke request unless <prerequisite web request> is successful, etc),
- extended response verifications ('contains', 'does not contain', xpath and response status verification),
- extended logging,
- and several various other features.
For reference here is the updated web resource type and provider:
lib/puppet/provider/type/web_request.rb
require 'uri' # A puppet resource type used to access resources on the World Wide Web Puppet::Type.newtype(:web_request) do @doc = "Issue a request to a resource on the world wide web" private # Validates uris passed in def self.validate_uri(url) begin uri = URI.parse(url) raise ArgumentError, "Specified uri #{url} is not valid" if ![URI::HTTP, URI::HTTPS].include?(uri.class) rescue URI::InvalidURIError raise ArgumentError, "Specified uri #{url} is not valid" end end # Validates http statuses passed in def self.validate_http_status(status) status = [status] unless status.is_a?(Array) status.each { |stat| stat = stat.to_s unless ['100', '101', '102', '122', '200', '201', '202', '203', '204', '205', '206', '207', '226', '300', '301', '302', '303', '304', '305', '306', '307', '400', '401', '402', '403', '404', '405', '406', '407', '408', '409', '410', '411', '412', '413', '414', '415', '416', '417', '418', '422', '423', '424', '425', '426', '444', '449', '450', '499', '500', '501', '502', '503', '504', '505', '506', '507', '508', ' 509', '510' ].include?(stat) raise ArgumentError, "Invalid http status code #{stat} specified" end } end # Convert singular params into arrays of strings def self.munge_array_params(value) value = [value] unless value.is_a?(Array) value = value.collect { |val| val.to_s } value end newparam :name newproperty(:get) do desc "Issue get request to the specified uri" validate do |value| Puppet::Type::Web_request.validate_uri(value) end end newproperty(:post) do desc "Issue post request to the specified uri" validate do |value| Puppet::Type::Web_request.validate_uri(value) end end newproperty(:delete) do desc "Issue delete request to the specified uri" validate do |value| Puppet::Type::Web_request.validate_uri(value) end end newproperty(:put) do desc "Issue put request to the specified uri" validate do |value| Puppet::Type::Web_request.validate_uri(value) end end newparam(:parameters) do desc "Hash of parameters to include in the web request" end newparam(:file_parameters) do desc "Hash of file parameters to include in the web request" end newparam(:follow) do desc "Boolean indicating if redirects should be followed" newvalues(:true, :false) end newparam(:store_cookies_at) do desc "String indicating where session cookies should be stored" end newparam(:use_cookies_at) do desc "String indicating where session cookies should be read from" end newparam(:remove_cookies) do desc "Boolean indicating if cookies should be removed after using them" newvalues(:true, :false) end newparam(:returns) do desc "Expected http return codes of the request" defaultto ["200"] validate do |value| Puppet::Type::Web_request.validate_http_status(value) end munge do |value| Puppet::Type::Web_request.munge_array_params(value) end end newparam(:does_not_return) do desc "Unexecpected http return codes of the request" validate do |value| Puppet::Type::Web_request.validate_http_status(value) end munge do |value| Puppet::Type::Web_request.munge_array_params(value) end end newparam(:contains) do desc "XPath to verify as part of the result" munge do |value| Puppet::Type::Web_request.munge_array_params(value) end end newparam(:does_not_contain) do desc "XPath to verify as not being part of the result" munge do |value| Puppet::Type::Web_request.munge_array_params(value) end end newparam(:log_to) do desc "Log requests/responses to the specified file or directory" end newparam(:only_log_errors) do desc "Boolean indicating if we should only log responses which did not pass validations" newvalues(:true, :false) end newparam(:if) do desc "Invoke request only if the specified request returns true" end newparam(:unless) do desc "Invoke request unless the specified request returns true" end newparam(:username) do desc "HTTP authentication username" end newparam(:password) do desc "HTTP authentication password" end end
lib/puppet/provider/web_request/curl.rb
require 'fileutils' # Provides an interface to curl using the curb gem for puppet require 'curb' # uses nokogiri to verify responses w/ xpath require 'nokogiri' class Curl::Easy # Format request parameters for the specified request method def self.format_params(method, params, file_params) if([:get, :delete].include?(method)) return params.collect { |k,v| "#{k}=#{v}" }.join("&") unless params.nil? return "" end # post, put: cparams = [] params.each_pair { |k,v| cparams << Curl::PostField.content(k,v) } unless params.nil? file_params.each_pair { |k,v| cparams << Curl::PostField.file(k,v) } unless file_params.nil? return cparams end # Format a url for the specified request method, base uri, and parameters def self.format_url(method, uri, params) if([:get, :delete].include?(method)) url = uri url += ";" + format_params(method, params) return url end # post, put: return uri end # Invoke a new curl request and return result def self.web_request(method, uri, params = {}) raise Puppet::Error, "Must specify http method (#{method}) and uri (#{uri})" if method.nil? || uri.nil? curl = self.new if params.has_key?(:cookie) && !params[:cookie].nil? curl.enable_cookies = true curl.cookiefile = params[:cookie] curl.cookiejar = params[:cookie] end if params.has_key?(:username) && !params[:username].nil? curl.username = params[:username] end if params.has_key?(:password) && !params[:password].nil? curl.password = params[:password] end curl.follow_location = (params.has_key?(:follow) && params[:follow]) request_params = params[:parameters] file_params = params[:file_parameters] case(method) when 'get' curl.url = format_url(method, uri, request_params) curl.http_get return curl when 'post' curl.url = format_url(method, uri, request_params) curl.multipart_form_post = true if !file_params.nil? && file_params.size > 0 curl.http_post(*format_params(method, request_params, file_params)) return curl when 'put' curl.url = format_url(method, uri, request_params) curl.multipart_form_post = true if !file_params.nil? && file_params.size > 0 curl.http_put(*format_params(method, request_params, file_params)) return curl when 'delete' curl.url = format_url(method, uri, request_params) curl.http_delete return curl end end def valid_status_code?(valid_values=[]) valid_values.include?(response_code.to_s) end def valid_xpath?(xpath="/") !Nokogiri::HTML(body_str.to_s).xpath(xpath.to_s).empty? end end # Puppet provider definition Puppet::Type.type(:web_request).provide :curl do desc "Use curl to access web resources" def get @uri end def post @uri end def delete @uri end def put @uri end def get=(uri) @uri = uri process_params('get', @resource, uri) end def post=(uri) @uri = uri process_params('post', @resource, uri) end def delete=(uri) @uri = uri process_params('delete', @resource, uri) end def put=(uri) @uri = uri process_params('put', @resource, uri) end private # Helper to process/parse web parameters def process_params(request_method, params, uri) begin error = nil cookies = nil if params[:store_cookies_at] if File.exist?(params[:store_cookies_at]) File.truncate(params[:store_cookies_at], 0) else FileUtils.touch(params[:store_cookies_at]) end cookies = params[:store_cookies_at] elsif params[:use_cookies_at] cookies = params[:use_cookies_at] end # verify that we should actually run the request return if skip_request?(params, cookies) # Actually run the request and verify the result result = Curl::Easy::web_request(request_method, uri, :parameters => params[:parameters], :file_parameters => params[:file_parameters], :cookie => cookies, :follow => params[:follow], :username => params[:username], :password => params[:password]) result_body = result.body_str.to_s verify_result(result, :returns => params[:returns], :does_not_return => params[:does_not_return], :contains => params[:contains], :does_not_contain => params[:does_not_contain] ) result.close rescue Exception => e error = e raise Puppet::Error, "An exception was raised when invoking web request: #{e}" ensure unless result.nil? log_response(:result => result_body, :method => request_method, :uri => uri, :puppet_params => params, :error => error) end FileUtils.rm_f(cookies) if params[:remove_cookies] end end # Helper to determine if we should skip the request def skip_request?(params, cookie = nil) [:if, :unless].each { |c| condition = params[c] unless condition.nil? method = (condition.keys & ['get', 'post', 'delete', 'put']).first result = Curl::Easy::web_request(method, condition[method], :parameters => condition['parameters'], :file_parameters => condition['file_parameters'], :cookie => cookie, :follow => params[:follow]) result_succeeded = true begin verify_result(result, condition) rescue Puppet::Error result_succeeded = false end return true if (c == :if && !result_succeeded) || (c == :unless && result_succeeded) end } return false end # Helper to verify the response def verify_result(result, verify = {}) verify[:returns] = verify['returns'] if verify[:returns].nil? && !verify['returns'].nil? verify[:does_not_return] = verify['does_not_return'] if verify[:does_not_return].nil? && !verify['does_not_return'].nil? verify[:contains] = verify['contains'] if verify[:contains].nil? && !verify['contains'].nil? verify[:does_not_contain] = verify['does_not_contain'] if verify[:does_not_contain].nil? && !verify['does_not_contain'].nil? if !verify[:returns].nil? && !result.valid_status_code?(verify[:returns]) raise Puppet::Error, "Invalid HTTP Return Code: #{result.response_code}, was expecting one of #{verify[:returns].join(", ")}" end if !verify[:does_not_return].nil? && result.valid_status_code?(verify[:does_not_return]) raise Puppet::Error, "Invalid HTTP Return Code: #{result.response_code}, was not expecting one of #{verify[:does_not_return].join(", ")}" end if !verify[:contains].nil? && !result.valid_xpath?(verify[:contains]) raise Puppet::Error, "Expecting #{verify[:contains]} in the result" end if !verify[:does_not_contain].nil? && result.valid_xpath?(verify[:does_not_contain]) raise Puppet::Error, "Not expecting #{verify[:does_not_contain]} in the result" end end def log_response(params) method = params[:method] uri = params[:uri] result = params[:result] error = params[:error] puppet_params = params[:puppet_params] if puppet_params[:log_to] return if puppet_params[:only_log_errors] == :true && error.nil? logfile = puppet_params[:log_to].strip exists = File.exists?(logfile) isfile = File.file?(logfile) || (!exists && (logfile[-1].chr != '/')) if !isfile FileUtils.mkdir_p(logfile) if !exists logfile += puppet_params[:name] end f = File.open(logfile, 'a') f.write("=====BEGIN=====\n") f.write(Time.now.strftime("%Y-%m-%d %H:%M:%S")) f.write(" #{method} request to #{uri}\n") f.write(result.to_s) f.write("\n=====END=====\n\n") f.close end end end
As always, Happy Puppeteering!
Fudcon Blacksburg Report
Submitted by mmorsi on Mon, 2012-01-16 12:47
Just got back from Fudcon Blacksburg. As always, it was a great time. Arrived after driving down (10 hrs) Thursday evening and crashed quickly after checking into my accommodations (The Inn at Virginia Tech). Friday, the first day, was hackfests, I attended the Fedora Infrastructure meeting and held a few sessions around Aeolus where I talked with passer by's about the project, my Snap subproject and what people were looking for out of an open source IaaS cloud abstraction platform. Specifically at FUDCon I aimed to find out how people wanted to interface w/ the cloud on the Fedora desktop and how they wanted to use the Aeolus stack. We ended up modifying Snap a little to add some command line options and began
messing around w/ mycloud a c level cloud computing API I started throwing together to meet people's needs. Dinner that night was at a good indian place.
The second day was the barcamp sessions, I volunteered to do another session on Aeolus, which went well, there were plenty of newcomers interested in the projects and I was able to share what was in development and upcoming things on the platform. After lunch several of us from the ruby-sig met to hold the now traditional ruby-sig meeting at FUDCon (we held one in Toronto, one was held in Milan, and now this was the third at Blacksburg). We got alot done including:
- tested out the new Ruby 1.9.3 repository (messed around w/ getting Aeolus working on MRI 1.9.3)
- discussed updates to the new packaging guidelines, and updates to the the ruby stack
- looked into possibly using macros to assist w/ building gems for multiple ruby interpreters on Fedora (jeroen volunteered to start investigating thing one, this would be a feature coming furthur down the pipeline)
- discussed the rvm / bundler ecosystems, and again how to drive and market the Fedora philosophy of a single supported stack while delivering the ultimate development platform for the ruby-community
- looked into continuing building tools and applications which to enhance the Ruby experience on Fedora, I volunteered to build a isitfedoraruby website (akin to itisruby19.org) to demo and highlight fedora on ruby and to start reaching out to the cloud-sig and other Fedora communities to promote and highlight the product/platform.
- continuing to extend / expand / improve gem2rpm, polisher, and other gem/rpm interoperability tools
Next I attended the session on OpenStack, a popular build-your-own-cloud platform (one of the platforms supported by deltacloud) and learned a bit more about the internals and how it is constructed. Finally the lightning talks session was the last on Saturday, and a must for any FUDCon attendee. There were many pitches, including several for new fedora components including hosted instances of mock infra apps, a discussion on what motivates and how to drive open source contributions, a demonstration on how to inject code into running Python processes using "parasite" by lmacken, an overview of foss@rit by remmy dekaukusburg and the narcissus web visualizations by ralph bean. I ended up pitching mycloud and snap again as well as my own Nethack Encyclopedia project, inviting fellow explorers of the mazes of menace to bring the guide :-)
FUDPub was fun, as always a good time, featuring bowling and lots of tastey food and held at the Blacksburg student center this time around.
I'm writing this from my hotel room Sunday morning as I pack up and prepare for the 10hr drive hack. Overall a great time, have plenty to keep me busy going forward, and am looking forward to the next FUDCon!
Forthcoming: MRI Ruby 1.9 in Fedora
Submitted by mmorsi on Tue, 2012-01-03 23:00
The Fedora Ruby SIG is in the process of updating the main Ruby package in Fedora to Ruby 1.9. We hope to get it in by Fedora 17, while shipping a Ruby 1.8 compatability package for those who wish to continue using the older version (though more and more upstream projects are phasing this out). Alternatively, since JRuby is now in Fedora, end-users may opt to utilize that interpreter for both Ruby 1.8 and 1.9 support.
The Ruby 1.9 effort is being led by Vit Ondruch who has done alot of the packaging work and submitted the initial guidelines draft, which we are currently discussing/revising on the mailing lists. They are largely an extension of the existing guidelines to better nail things down and cover various issues that have come up over the years, but all are welcome to join the discussion and share their comments / opinions on the best way to move forward.
A Ruby 1.9.3 testing repository has been setup for those who wish to try the new packages out. Feel free to share any feedback or issues on list.
Book Review: Altered Carbon
Submitted by mmorsi on Sun, 2012-01-01 14:35
Having finished my long trek through Anathem a little while back, I was left craving for another epic sci-fi tale. Living up to his previous classic, Snow Crash, Neal Stephenson's Anathem is an amazing thrill-ride, full of intense action, profound philosophy (drawing on thousands of years of mathematics, science, and metaphysics), and overall an unbelievable story. Stephenson is truly a remarkable author, and while he deals with very-deep topics, there is a good chance that anyone will be able to find at least one of his worlds that draws them in. Surprisingly I couldn't get into Cryptonomicon when I tried not too long ago, but admittedly I didn't get terribly far into it before I gave up and might have to give it another go. There are plenty of reviews of Anathem online, so I will leave it up to my readers to read more about it through those, but needless to say I highly recommend the novel.
I ordered two books with relatively good reviews off of Amazon, Hyperion (a space opera) and the second being Altered Carbon by Richard K Morgan, a nitty gritty cyberpunk tale similar to Snow Crash. I tried the former first, but again try as I might I could not get into it, so I decided to give Altered Carbon a go, and was very pleasantly surprised.
Altered Carbon is the tale of Takeshi Kovacs as he investigates the 'murder' of Laurens Bancroft, a very rich and powerful business magnate in futuristic San Francisco, now called Bay City. By this point in time, actual real deaths are fairly uncommon, as it is a widespread practice to store one's identity, memories, and conscience 'on stack', which is able to be downloaded into temporary bodies known as 'sleeves' at any point in time after. Morgan's vivid and rich imagery paints a world that lives up to any cyberpunk setting portrayed to date, including perhaps the ultimate cyberpunk novel, Neuromancer by William Gibson. Chalk full of concepts such as virtual-realities, technology based augmentations, drug induced psychological and physiological alterations, interstellar travel, conspiring artificial intelligences, oriental philosophy, intense martial arts action, and much more, Kovacs' investigation keeps the reader glued to the edge of his/her seat and makes it hard to put the book down even for a second.
The novel is a good read, not so challenging that it will be lost on anyone (unlike Anathem and Snow Crash which are complete mind-benders), but also not too simplistic that it will bore. The chapters are fairly short and to the point, making for a good airplane or subway read, while the overall story fits together and flows nicely. Without spoiling any more, I highly suggest it to anyone that is into the genre, it won't disappoint!
Messing around w/ HTML5: drag-n-drop
Submitted by mmorsi on Fri, 2011-12-23 00:25In my last html5 blog post we explored using the canvas to recreate a simple version of pong. This time around we'll be using the drag-and-drop features of HTML5 for a simple example. Note I'm pulling in the JQuery UI library to take care of alot of the details and provide a easy-to-use interface to use drag-and-drop.
In this example, we have a list of images which we'd like to pull into a common area. The thing is, the original list should be preserved, once dragged-in, an image should not disappear from its original location.
This is accomplished by using jquery to set the images in the list to being draggable (this registers the necessary event handlers), and to make the common area droppable, eg able to receive draggable objects. JQuery allows us to set the 'helper' attribute, which defines the element being dragged around, to the predefined 'clone' value which makes a copy of the original element. From there we expand the container div to accept only the elements we want to drag in, and override the 'drop' method to set various properties allowing us to position and style the dropped element any way we would like.
All in all the effect is the following:
And the source producing this:
<div id="jquery_drag_drop_example_container"
style="width: 300px; height: 300px; background: #C0C0C0; float:left;">
</div>
<div style="background: #FFFF99; float:left; width: 20%; margin-left: 10px;">
<ul style="list-style-type: none; list-style-position: inside;">
<li><img class="jquery_drag_drop_example_img" src="example_0.png" /></li>
<li><img class="jquery_drag_drop_example_img" src="example_1.png" /></li>
<li><img class="jquery_drag_drop_example_img" src="example_2.png" /></li>
<li><img class="jquery_drag_drop_example_img" src="example_3.png" /></li>
<li><img class="jquery_drag_drop_example_img" src="example_4.png" /></li>
</ul>
</div>
<div style="clear: both;"></div><script type="text/javascript"> $(function(){ $('.jquery_drag_drop_example_img').draggable({ helper: 'clone', }); $('#jquery_drag_drop_example_container').droppable({ accept: '.jquery_drag_drop_example_img', drop: function(event, ui){ var newitem = $(ui.draggable).clone(); $(this).append(newitem); $(newitem).addClass("jquery_drag_drop_example_img_clone"); $(newitem).removeClass("ui-draggable jquery_drag_drop_example_img"); $(newitem).draggable({containment: 'parent'}); $(newitem).css('position', 'absolute'); $(newitem).css('top', ui.position.top ); $(newitem).css('left', ui.position.left); //alert(event.dataTransfer.getData('text')); } }); }); </script>
Thats it until next time. Hope everyone enjoys the holidays!










