source

Cloudstack 4.2.x Loadbalancer Stickness Policies

Recently while updating an application to consume the cloudstack 4.2.x API I started to run against some issues regarding the loadbalancer stickness policy attribute validation.

On version 4.1.x and lower the API CreateLBSticknessPolicy would accept the policy attributes as raw values, however, on 4.2.x it started to complain about some validation rules.

Screen Shot 2014-02-05 at 12.20.22 PM

There are several things wrong here, lets start from the beginning:

1.
The rest api has a very rudimentary interface to deal with policy parameters, instead of defining a key for each supported parameter it forces you to create a string matching this format

param[0].name=cookiename&param[0].value=LBCookie

That’s not even a json obejct/array. It is just a plain string which creates some overhead when you are consuming the api since you need to parse the params manually.
Plus there is no way to know which attributes are valid or not, you need to dig in on the documentation or the source code to see what is accepted by the api.

2.
Leaving the api interface aside, I started to look at the UI to check which format they were sending the requests. To my surprise I got the same error I was getting when consuming the api from a third party app.
Screen Shot 2014-02-05 at 12.25.39 PM

As you can see from the picture above there is not indication of what the format should be.
Looking at their docs there is also no mention.

3.
With no choice I had to dig through their source code.
Doing a full search on the project for the string “Failed LB in validation rule id
I found two occurrences:

This is the piece that does the validation:

 
 public static boolean validateHAProxyLBRule(LoadBalancingRule rule) {  
 String timeEndChar = "dhms";

 for (LbStickinessPolicy stickinessPolicy : rule.getStickinessPolicies()) {  
 List> paramsList = stickinessPolicy  
 .getParams();

 if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(  
 stickinessPolicy.getMethodName())) {

 } else if (StickinessMethodType.SourceBased.getName()  
 .equalsIgnoreCase(stickinessPolicy.getMethodName())) {  
 String tablesize = "200k"; // optional  
 String expire = "30m"; // optional

 /* overwrite default values with the stick parameters */  
 for (Pair paramKV : paramsList) {  
 String key = paramKV.first();  
 String value = paramKV.second();  
 if ("tablesize".equalsIgnoreCase(key))  
 tablesize = value;  
 if ("expire".equalsIgnoreCase(key))  
 expire = value;  
 }  
 if ((expire != null)  
 && !containsOnlyNumbers(expire, timeEndChar)) {  
 throw new InvalidParameterValueException(  
 "Failed LB in validation rule id: " + rule.getId()  
 + " Cause: expire is not in timeformat: "  
 + expire);  
 }  
 if ((tablesize != null)  
 && !containsOnlyNumbers(tablesize, "kmg")) {  
 throw new InvalidParameterValueException(  
 "Failed LB in validation rule id: "  
 + rule.getId()  
 + " Cause: tablesize is not in size format: "  
 + tablesize);

 }  
 } else if (StickinessMethodType.AppCookieBased.getName()  
 .equalsIgnoreCase(stickinessPolicy.getMethodName())) {  
 /*  
 * FORMAT : appsession len timeout  
 * [request-learn] [prefix] [mode  
 * ]  
 */  
 /* example: appsession JSESSIONID len 52 timeout 3h */  
 String cookieName = null; // optional  
 String length = null; // optional  
 String holdTime = null; // optional

 for (Pair paramKV : paramsList) {  
 String key = paramKV.first();  
 String value = paramKV.second();  
 if ("cookie-name".equalsIgnoreCase(key))  
 cookieName = value;  
 if ("length".equalsIgnoreCase(key))  
 length = value;  
 if ("holdtime".equalsIgnoreCase(key))  
 holdTime = value;  
 }

 if ((length != null) && (!containsOnlyNumbers(length, null))) {  
 throw new InvalidParameterValueException(  
 "Failed LB in validation rule id: " + rule.getId()  
 + " Cause: length is not a number: "  
 + length);  
 }  
 if ((holdTime != null)  
 && (!containsOnlyNumbers(holdTime, timeEndChar) && !containsOnlyNumbers(  
 holdTime, null))) {  
 throw new InvalidParameterValueException(  
 "Failed LB in validation rule id: " + rule.getId()  
 + " Cause: holdtime is not in timeformat: "  
 + holdTime);  
 }  
 }  
 }  
 return true;  
 }  

Which is the same in both classes, only difference is the formatting.
Actually, the whole class re-implements most methods, not sure why they can’t share a helper class or extend some base class that implements the common methods.
Might be that they are treated as separated projects so there are some dependencies overhead involved.
Anyway, the validation itself is pretty straight forward for SourceBased rules:

  • table size attribute must end with k, m or g
  • expire attribute must end with d, h, m, or s.

Trimming spaces and comments in C

This is a simple C function that reads a line from a file and trim all comments and spaces.
You can see that the function receives a pointer to a file, a pointer to a char and an integer holding the size of the line to be read from the file.
The function then returns a line from the file without spaces(leading/trailing) and comments

Function signature:

 
 char * readLine (FILE* fp, char* line, int size)  

One thing I want to point out is the fact that it is possible to trim the string without creating a new one.
By using pointer arithimetics you can manipulate the chars of the line and remove anything you want.

For example, lets say you have a string like this:

*I’m using 0x00n just as an example to demonstrate the memory location of each char.

So the string A1 has two leading and trailling spaces.
Assuming that the line read from the file is: ” a1 ”

1.

First we remove the comments, none is this case:

   
 s = strchr(line, ‘#’);  
 if (s) *s = ‘\0';  

We use strchr to search the string for any occurrences of #

If # is found in the string we set the null byte to the position of the first #

2.

The next step is to remove all the trailing spaces:

 
 s = line + strlen(line) – 1;  
 while (isspace(*s)) s–;  
 *(s+1) = ‘\0';  
  • First we assign to s the position of the last char in the line string.

  • Second we check if the char is a space using the isspace function(it checks not only for spaces, but for other delimiters as well). If the char is a space we subtract one from the s, meaning we subtract a char from s, setting s to point to one char before.

  • Once we find a char that’s not a space we break the loop.

  • Finally, we add one to s, and set the null byte to the position of the first space after the string ends.

3.

To remove leading spaces is even simpler:

 
 s = line;  
 while (isspace(*s)) s++;  

We set s to point to the first char in the string read from the file.
Then we loop through the string checking if the char is a space and incrementing the pointer by 1.

After all the trimming, s will point to the first non space char in the string, and the null byte will be positioned right after the last non space char. It will also have all the comments removed.

One thing to notice with this approach, is that the function must receive a char* and return a char.
The reason beginning is that the char
needs to be declared in the function that is calling readLine, in this example the main. Since if not, the scope of the char* would be tight to the readLine function and thus the calling function would not be able to access the trimmed string.

Another possibility could be to manipulate the char* line itself, removing the necessity to return a new char.

This trim function could be adapt to not only work with files, but with different data structures as well.

If you have any suggestions or tips please leave a comment bellow :D

Full Source Code:

  
 #include  
 #include  
 #include

char *  
 readLine (FILE* fp, char* line, int size)  
 {  
 char* s = NULL;

 while (!feof(fp) && fgets(line, size, fp)) {  
 // Strip comments  
 s = strchr(line, ‘#’);  
 if (s) *s = ‘\0';

 // Remove trailling spaces  
 s = line + strlen(line) – 1;  
 while (isspace(*s)) s–;  
 *(s+1) = ‘\0';

 // Remove leading spaces  
 s = line;  
 while (isspace(*s)) s++;

 // Don’t return empty lines  
 if (*s) return s;  
 printf("empty linen");  
 }

 return NULL;  
 }

int  
 main (void)  
 {  
 FILE* fp = NULL;  
 char line[256];  
 char* s = NULL;  
 fp = fopen("file", "r");  
 if (!fp) return 1;  
 while ((s = readLine(fp, line, sizeof(line)))) {  
 printf("s: %s. || line: %s.n", s, line);  
 }  
 return 0;  
 }  

Test file:

start
a1
a2
a3 #other comment
end

start
b1
b2
start
c1#comment….
c2
end
end
[/sourcecode]

Debug Build of Firefox on Ubuntu

Following the tutorial on MDN  and with the help of the #developer channel on IRC I was able to build firefox in debug mode.
These are the steps I followed to get the build working:

Install dependencies:

apt-get build-dep firefox
apt-get install mercurial libasound2-dev libcurl4-openssl-dev libnotify-dev libxt-dev libiw-dev mesa-common-dev autoconf2.13 yasm

Create .mozconfig file in the root of your project

. $topsrcdir/browser/config/mozconfig
mkaddoptions MOZOBJDIR=@TOPSRCDIR@/ff-dbg
ac
addoptions –disable-optimize
ac
addoptions –enable-debug
ac
add_options –enable-tests

Then

make -f client.mk build

It took me around 1h 10min to finish the build

To run firefox:

cd ff-dbg/dist/bin
./firefox

For some reason, when I start the browser, after a few seconds it goes to sleep and crashes

Also if I try to run the firefox-bin I get this error: