CENTOS 6 (RHEL 6) KVM Bridged Networking With Static IP on Host HowTo

Edit: Everything described here can be accomplished in the Virtual-Manager GUI, but this is here for all the CLI junkies.

I decided to take the time to write up a quick HowTo for configuring RHEL 6 or any of it’s clones (CentOS 6 and Scientific Linux to name a couple) so that KVM can use your main network device for bridged connections on your VMs. Some virtualization solutions make bridge connections pretty simple and automatic. KVM requires (from everything I’ve seen at least) a little more hands-on configuration.

I’ve collected this information from various sources. One of the things I’ve noticed is that most sources advise you to stop the NetworkManager service and to disable it at boot. I agree with this as we are going to be doing more advanced configurations of our network devices and automated tools like NetworkManager are best for more basic setups where the user doesn’t want to fiddle with the configurations manually. So you’ll want to do the following as root:

chkconfig NetworkManager off
chkconfig network on
service NetworkManager stop
service network start

In this example I’ll be using eth0 as my physical network device. You may be using eth1 or some other device. Make sure to replace eth0 with your actual network device. In most cases it is eth0.

ifdown eth0

Now create a bridge device. We are going to call it bridge0. If you’ll notice in /etc/sysconfig/network-scripts you’ll see configuration files for your network devices. You should see one for eth0. It will be called ifcfg-eth0. Edit that file. If you use a static IP address you’ll actually set that up in the bridge0 device configuration file later. Change the ifcfg-eth0 file to look like this (leave the HWADDR line alone, I’m leaving it out of the below example because it will be different on each machine):

DEVICE="eth0"
BOOTPROTO="none"
NM_CONTROLLED="yes"
ONBOOT="yes"
BRIDGE="bridge0"

Now we have told eth0 to use the bridge “bridge0″. We now need to create the configuration file for that bridge. Edit/Create the file /etc/sysconfig/network-scripts/ifcfg-bridge0 and add these lines:

DEVICE="bridge0"
TYPE="Bridge"
BOOTPROTO="static"
ONBOOT="yes"
DELAY=0
IPADDR=192.168.1.5
GATEWAY=192.168.1.1
DNS1=192.168.1.1

Save it and let’s start eth0 back up along with the new bridge:

ifup eth0
ifup bridge0

Now if you look at an ifconfig your bridge device will have your static IP of 192.168.1.5 (you can change this to your own static IP of course). Now in your KVM virtual machine manager, you’ll be able to use bridge0 as your bridge network device. Any VM that connects to that bridge will be able to get a DHCP IP address from the router or it can be configured with a static IP.

Be wary of Firewall rules on the host machine. Check those first if you have any access issues on the guest.

Questions/Comments are welcome.

Relational Database Design Woes

Every college course you could take will explain “proper” database design in terms of normalizing data into many smaller tables of related data. We are taught to think of tables much like we think of objects in object oriented programming. For consistency, this works out great. It keeps the data in its proper place. I’ve seen many database designs that made me laugh in the past. They would not be normalized, and I always had this smug attitude toward this improper database design. It was obvious to me that it was designed by someone who didn’t have a grasp on proper relational database design.

I was an idiot. Anyone who thinks proper relational database design is the best way to do things has never had a large, high traffic database to maintain and optimize. Proper relational database design works fine for small projects and low traffic CMS systems, but don’t expect it to work well for something larger. I spent days designing my latest database project. I thought I had developed a great database design. It was normalized well. I had JOINS combining my data in nice, easy to use views.

Within a day or two of high traffic inserts, one of my tables was starting to get a large amount of rows. I had a couple of indexes on this table to make sorting and such faster. A simple select statement performed extremely well. However, to my dismay, a join that used this table was already excruciatingly slow. Now anyone who knows anything about database design knows that you can’t expect a JOIN on a huge table to be fast, but they may over-estimate the definition of a “large” table. After only around 50,000 rows, this table was almost unusable in a join.

At that point, I began to ask, “What’s the point of having the ability to join tables, if it takes this long at such a small size?” I think the answer to that has more to do with cheap hardware costs. Instead of optimizing the database, most companies probably just add more clustered computers. This is all well and good, but it seems like a huge waste of resources, in the name of sticking to the “proper” relational database design. I’m also well aware of the different points to relational databases and that I’m only hitting on one. Performance isn’t the only concern of some people. Data availability and consistency are also major factors.

Which leads me to something I used to think about SQL databases, and I feel that I’m vindicated in this regard. I once thought that I didn’t need the major features of RDBMS. I could handle all the relational parts via the programming language itself. Now this does bring up data integrity issues, but lets be honest. If there are data integrity issues in the program they are more than likely going to be there either way. We can say that it’s more difficult to have integrity issues if we stick to a proper relational model, but that may not be the case. The data is still being manipulated by the programmer in either case. I would actually say that there’s more of a chance of injecting bad data into a database by using proper relational database techniques.

For instance, imagine a table called `example` with a few fields but two in particular: `id` and `foreign_id`
Now say that there over 900,000 of these records in the database and you want to count and group the records by the `foreign_id`. You would use a query like:

SELECT COUNT(`id`), `foreign_id` FROM `example` GROUP BY `foreign_id`;

On my server, on a similar table, this query takes 0.73 secs to execute. Now that’s pretty fast and can be improved with caching and such, but if that query were added to a view with other summarizing data and a few joins, it suddenly goes from being a slightly less than 1 sec query to a 30 second query.

There are a few solutions to making this faster. One is to run the query in a cron and cache the data in a separate table. One important aspect of this example table in my production environment is that the 900,000 records aren’t useful for anything but creating this summary data. My point… the data is never looked at in detail. Here’s where you move away from the typical relational db techniques. For data integrity, we should give up the performance and leave all these records in there as they are. However since we only need a the summary, we can remove most of the records and add their calculations to a separate table. This table can be queried in a fraction of the time.

I think my main point here is that you will typically start out with a proper relational database, but that design doesn’t really take into consideration performance. If you have to optimize your database, you’ll be steering completely away from the relational model. You’ll have to do things that seem like hacks, and you may even get smug looks on your database design by others later on, but they won’t realize that you started out with good intentions and had to make sacrifices to get the database to perform as required. You actually have a better understanding of how things work in the real world than those smug relational zealots.

But some of you may disagree. Please tell me where I’m wrong. I know there are plenty of experts out there on the internets.

Pushpool Errors

Over the last few days, I’ve been learning a lot about MySQL, and that’s definitely helping me see the light on a few database optimization techniques, namely JOINs aren’t always a good idea. In fact, I’m starting to hate the whole relational database model all together. I may be looking into better solutions down the road.

On top of that, I’ve been learning a lot about the various pieces of software needed to run a Bitcoin mining pool. First off, let me say that the developers responsible for pushpool are awesome and none of this is meant to be bad towards them. In fact, I tend to blame my own ignorance on most issues like this. However, I’ve been having a lot of trouble keeping pushpool running stable. With our pool at around 6 gh/sec it tends to become unresponsive after about 8 hours. There’s probably some documentation on pushpool somewhere that I’ve failed to read, though it’s not readily apparent where such documentation may be located.

So I’ve resorted in using a technique I learned from dealing with HP Service Center and Windows XP. When in doubt, recycle the app. I’ve setup a cron every four hours to check if pushpool is running and restart/start the app. If you are having trouble with pushpool dying, you may want to give it a try.

I’m making it available to anyone who wants to use it. If it’s useful, send BTC donations to:
16bKomVHmFERqzsSQrbX5rSHmjKuoiesJw

Here’s the python script source:

#!/usr/bin/python
 
import commands
 
output = commands.getoutput("ps aux")
 
if 'pushpool' in output:
	pppid = commands.getoutput("pidof pushpoold")
	print "Killing pushpoold (", pppid, ")"
	killcommand = "kill -15 " + pppid
	if commands.getstatusoutput(killcommand):
		print "Killed Pushpool..."
		print "Restarting..."
		print commands.getstatusoutput('/usr/local/sbin/pushpoold -D 2 --config /etc/pushpool.json')
 
else:
	print "Pushpoold isn't running. Starting it..."
	print commands.getstatusoutput("/usr/local/sbin/pushpoold -D 2 --config /etc/pushpool.json")

Make sure to change the obvious parts, such as the location of the pushpool executable on your system and the location of the config file.

Name the script whatever you want and cron it for however often you need it to run.

July 7th update on our Bitcoin Mining Pool

Well, we are in day three of our bitcoin mining pool and it has been very fun. I’m always learning new things and today really gave me a better understanding of the performance decreases one can run into by using SQL VIEWS, if one is not careful.

We wanted to give our users quick updates on their bitcoin miner stats so I used a few views and some joins. One of the views had a few nested SELECT statements. I really didn’t think that I’d see the slowness this early on but those nested SELECT statements within the view really took their toll on performance. We quickly started seeing three to five second page loads. So I knew it was time to start caching more data.

My caching technique was pretty simple-minded but it does the trick. I simple created physical tables identical to the views and added some crontab tasks to update the physical tables with the up-to-date data from the views. The pages now load pretty swiftly. I have a feeling that we will need some more powerful hardware soon, especially with the current rate of increase of users.

Most of the big bitcoin mining pools are getting hit by DDOS attacks. We’re just chugging along and picking up miners without homes while all of that is going on. So if you have a miner without a home, point it at our bitcoin mining pool.

Bithasher Grand Opening – Exciting Day

Lynn and I have had an exciting day. We opened the doors on our beta bitcoin mining pool. I didn’t expect to get any users today, but we actually have quite a few joining. With the massive DDOS attacks against the other pools, many people are without a mining pool to connect to. Some of them may venture to our little pool. We surged pass 3 ghash/sec earlier today but it has dropped back down to 2.8 ghash/sec. We’ll be celebrating the milestones. Anyone that wants to join it is welcome to help us test it out.

http://bithasher.com

It’s my blog and I’ll spam if I want to….spam if I want to…spam if I want to….You would spam too if it happened to you.

Best Bitcoin Mining Pool

We just opened the pool. There are many enhancements to the site that I have on the “todo” list, but all the core functions are present. Check it out at http://bithasher.com.

Frontend for pushpoold

My friend Lynn and I have been working on starting a bitcoin mining pool. I’ve opted to write my own frontend for pushpoold/bitcoind. At first I was going to use simplecoin and modify it to my liking, but it’s just not for me. The mixture of coding techniques in the project, along with a large margin for error in many places made me have a bad taste in my mouth fairly early when looking at the code.

Don’t get me wrong. It’s commendable work, but there’s a huge lack of planning to the project from what I can see. Scripts are thrown into place, and though they work, they are terrible from a maintenance perspective. I mean very little disrespect to the developers. I think I’ve been looking at so much OOP PHP for the past year or so that the procedural layout used in simplecoin just appears more ugly than it really is.

Stay tuned for that finished product.

Compiling PushPool on CentOS 5.6

I’ve just had a full day of troubleshooting a single issue, and I thought it would be a good one to share here. A friend and I are setting up a bitcoin mining pool. We are going to run it on a server which uses CentOS 5.6 and Direct Admin. I was able to get bitcoind running pretty easily, but pushpoold was a little more difficult. The first problem I ran across was related to a missing aclocal macro. I eventually fixed that problem by adding a libcurl.m4 macro. If you need help with that, I can look back and see how I did it. Just post a comment.

After I worked through the libcurl issue, I ran into another roadblock. This one was related to htole32 and le32toh. Both of these are functions introduced in glibc 2.9. Prior versions of glibc DO NOT WORK. The version of glibc included with CentOS 5.6 is earlier than 2.9. So eventually I happened upon this bit of code. It was in one of the commits of a git branch of pushpool. I must admit, I’m fairly ignorant when it comes to the inner workings of git. That’s about to change. At any rate, the change was presented as a few additional lines to the msg.c and server.c files. However, as pointing out by the original author (although not committed to the original branch) the code should be added to server.h instead, as it’s included in both msg.c and server.c. Here is the code that needs to be added near the top of server.h.

// Compatibility with glibc < 2.9
#if !defined(htole32) && !defined(le32toh)
#  include <byteswap.h>
#  define htole32(x)  (bswap_32(htonl(x)))
#  define le32toh(x)  (ntohl(bswap_32(x)))
#endif 
 
//Disregard this part of the code. There is an error in this syntax 
//highlighting plugin apparently.

Include the hashes, this is not a comment. This bit of code should go before the struct hist; declaration.

Hope this helps others! I sure could have used it.

HY093 PDO Error

I get this error enough to be a nuisance. It’s not that it’s PHP or PDO’s fault. I simply made a typo that resulted in this error. The problem with this error is that it doesn’t really give you a good clue as to what’s going on. In fact, it probably comes up for various reasons, but here is why it came up for me. When you are blurry eyed from coding, sometimes the simplest mistakes are very frustrating to troubleshoot. We all go through those, but here’s the one that just got me with a HY093 Error in PDO.
For this example $query$this->odb is my PDO object. So I’ve already done this:

$q = "SELECT `votes`.`id` FROM `votes` JOIN `comments` ON 
        `votes`.`comment_id`=`comments`.`id` WHERE `user_id`=:user  
         AND `topic_id`=:topic;";
// $this->odb is a PDO object I have defined for the class in this case
$query = $this->odb->prepare($q);
$query->execute(array(":user" => $user, ":topic_id" => $topic));

Do you see the error? It’s pretty obvious when you only have that bit to look at and you have a clear head. This is one of those simple hiccups that causes a little frustration. On top of that, the PDO error simply says “HY093″. That’s very informative.

The error, in case you don’t see it, is in the execute. The list of fields doesn’t match those used in the prepare statement. They are close enough to not be easy to spot. The “:topic_id” should be “:topic”, but PDO doesn’t just tell you that your fields don’t match. PDO does tell you that your fields don’t match if they are out of order, but not if they are completely wrong. At least, that’s my experience. So if you see an error HY093, you should check your field binding.

EnduraPro – First Impressions

I’ve owned an IBM Model M keyboard for a while now. I love typing on it. However, I’ve tinkered with it enough to mess up the key alignment on the left CTRL key. This was entirely my fault and in no way some defect in the Model M. Also it should be noted that my Model M is a Part NO: 52G9658. It was made in 1993. At the time of this writing, it is 18 years old. It looks like it’s brand new and it types like a dream.

So, finding a keyboard that compares well to my Model M was a challenge. You can tell that I love my Model M. To me, it is the ultimate typing experience. Since I program, a faulty CTRL key can wreak havoc on my productivity. So I required a new keyboard. My first purchase was a Dell AT101W. It is a great alternative to the Model M, but has a completely different feel. It isn’t a “clicky” keyboard, but it is a loud vintage keyboard with tactile mechanical keys.  I bought it on eBay for $20. I typed on it while I waited on my next keyboard, which I found at PCKeyboards.com.

This new keyboard is called the Unicomp EnduraPro. Unicomp owns the rights to manufacture spring buckling Model M replica keyboards. They have a full line of them. The Endurapro is around $100 and is basically a Model M with an integrated Trackpoint pointing device. I ordered it because I thought the Trackpoint would be a good addition and could come in handy.

The shipping was quick but I ordered toward the end of the week. So, it didn’t arrive until Monday evening. Which leads me to now. I’m sitting at my desk typing like a mad man on a new post to my blog on the EnduraPro.

My first impressions are as follows:

  • It has a slightly different feel than the Model M. At first it had a dirty feel to it, for lack of a better word to describe it. It feels almost as if there is some sand in the keys. My Model M has a much cleaner feel. It still has the resistance but doesn’t feel like I’m scratching something as I type. I can say, however, that after typing on it for a while, either that feeling is going away or I’m getting used to it.
  • The keys feel a little closer together. The keys may not be, but this is the feeling I get from the keyboard. It may be due to the next issue.
  • The Trackpoint is in the way. I had to take the red cap off the Trackpoint just to be able to type g, h, and b properly. I had a lot of trouble typing these letters fluidly with it there.
  • The Trackpoint functions, but it isn’t a very good pointing device. You have you push it very hard to get the pointer to move at a decent rate.

Other than these things, this keyboard is awesome. The Trackpoint is there if you need it, but it’s not going to be your primary pointing device probably. If I could go back and do it all over again, I’d order the Customizer 104 instead. The Trackpoint is actually in the way.

After a few hours of use, the keyboard feels more like the original Model M. I will post again in a day or so, hopefully, with more details.