Welcome to zewaren.net. This site presents myself and mostly archives the solutions to some problems I once had.

How to allow specific IPs to connect to a lighttpd webserver, and have the others use mod_auth

Image

Situation

You protect your web applications using lighttpd's mod_auth.

You'd like to have some users (say, your office) access the server without having to log in.

Configuration

Filter the configuration based on your users' IPs.

$HTTP["remoteip"] != "203.0.113.92" {
    auth.backend = "ldap"
    auth.backend.ldap.hostname = "10.0.10.13"
    auth.backend.ldap.base-dn  = "ou=people,dc=example,dc=com"
    auth.backend.ldap.filter   = "(&(uid=$)(memberOf=cn=some_group,ou=sgroups,dc=example,dc=com))"
    auth.backend.ldap.bind-dn  = "cn=our_lighttpd_user,ou=services_ro,dc=example,dc=com"
    auth.backend.ldap.bind-pw  = "qdkdfsgbxxcvbiuoisj"
    auth.backend.ldap.allow-empty-pw = "disable"
    auth.require = ( "" => (
            "method"  => "basic",
            "realm"   => "Our superb realm",
            "require" => "valid-user"
        )
    )
}

If you're using a reverse proxy, use mod_extforward to retrieve the correct IPs.

server.modules += ( "mod_extforward" )
extforward.forwarder = ("198.51.100.156" => "trust")

Reference:

How to apply FreeBSD10's autotools patches manually

The FreeBSD logo Image

Situation

You're manually building something that require autotools on FreeBSD 10.

You're used to the port system patching your autotools files, and you want to apply theses patches to your current folder.

Script

Choose your poison:

/bin/tcsh

foreach f (`find . -type f \( -name config.libpath -o -name config.rpath -o -name configure -o -name libtool.m4 -o -name ltconfig -o -name libtool -o -name aclocal.m4 -o -name acinclude.m4 \)`)
    sed -i.fbsd10bak -e 's|freebsd1\*)|freebsd1.\*)|g' -e 's|freebsd\[12\]\*)|freebsd[12].*)|g' -e 's|freebsd\[123\]\*)|freebsd[123].*)|g' -e 's|freebsd\[\[12\]\]\*)|freebsd[[12]].*)|g' -e 's|freebsd\[\[123\]\]\*)|freebsd[[123]].*)|g' $f
    touch -f -mr $f.fbsd10bak $f
    rm $f.fbsd10bak
end

/bin/sh:

for f in `find . -type f \( -name config.libpath -o -name config.rpath -o -name configure -o -name libtool.m4 -o -name ltconfig -o -name libtool -o -name aclocal.m4 -o -name acinclude.m4 \)`; do
    sed -i.fbsd10bak -e 's|freebsd1\*)|freebsd1.\*)|g' -e 's|freebsd\[12\]\*)|freebsd[12].*)|g' -e 's|freebsd\[123\]\*)|freebsd[123].*)|g' -e 's|freebsd\[\[12\]\]\*)|freebsd[[12]].*)|g' -e 's|freebsd\[\[123\]\]\*)|freebsd[[123]].*)|g' $f
    touch -f -mr $f.fbsd10bak $f
    rm $f.fbsd10bak
done

How to extract the windows license key from a Lenovo T440p recovery CDs.

Image Image

Situation

You own a Lenovo T440p with Windows 7 preinstalled, but you have Windows 8 recovery CDs. Unfortunately, your laptop doesn't include a CD drive.

You'd like to extract the Windows License key from the CD and install your computer yourself with a custom image (I mean, who would use a preinstalled Windows image with Norton Security for anything serious).

Chapter 1: extract the key from the CD

Five CDs were provided by Lenovo:

  • (1) Windows 8 Recovery Media for Windows 8 Products (Disk 1 of 2)
  • (1) Windows 8 Recovery Media for Windows 8 Products (Disk 2 of 2)
  • (2) Operating System Recovery Disk Windows 8 Pro (OEM Activation 3.0 Required) (Disk 1 of 2)
  • (2) Operating System Recovery Disk Windows 8 Pro (OEM Activation 3.0 Required) (Disk 2 of 2)
  • (1) Windows 8 Recovery Media for Windows 8 Products (Disk 1 of 1)
  • Office pro 2013

My guess is that we'll find what we need in the largest file contained in the CDs, which should be a Windows installation image.

This file is: M8S4AUS.swm. This looks like a split WIM file.

Let's merge it and open it.

E:\RECOVERY>imagex /export /ref M8S4AUS*.swm M8S4AUS.swm 1 exported.wim "exported"

ImageX Tool for Windows
Copyright (C) Microsoft Corp. All rights reserved.
Version: 6.3.9600.16384

Exporting: [E:\RECOVERY\M8S4AUS.swm, 1] ->
           [E:\RECOVERY\exported.wim]
[ 100% ] Exporting progress

Successfully exported image #1.
Total elapsed time: 15 min 49 sec
imagex /MOUNT exported.wim 1 c:\truc

ImageX Tool for Windows
Copyright (C) Microsoft Corp. All rights reserved.
Version: 6.3.9600.16384
Mounting: [E:\RECOVERY\exported.wim, 1] -> [c:\truc]...
[ 100% ] Mounting progress
Successfully mounted image.
Total elapsed time: 42 sec

Let's see what's inside.

E:\RECOVERY>dir c:\truc

 Volume in drive C has no label.
 Volume Serial Number is 2E2F-1418

 Directory of c:\truc

2014-10-08  18:30    <DIR>          .
2014-10-08  18:30    <DIR>          ..
2012-07-26  09:33    <DIR>          PerfLogs
2013-03-25  23:07    <DIR>          Program Files
2013-03-25  23:07    <DIR>          Program Files (x86)
2013-03-26  15:02    <DIR>          SWWORK
2013-03-25  23:03    <DIR>          Users
2013-03-26  00:15    <DIR>          Windows
               0 File(s)              0 bytes
               8 Dir(s)  22,738,112,512 bytes free

Bingo! This definitely looks like a Windows image.

Download and start ProduKey. Open the Select Source window and Load the product keys from external Windows directory.

Image

Voilà, the associated Microsoft keys are extracted and displayed.

Image

Chapter 2: extract the key from the BIOS

Unfortunately, we did chapter 1 for nothing, since the key R3C2N-HT63Q-F4RKH-KPP3R-3667Q is a generic key called: Windows® 8 Default Product Keys to be used with OEM Activation 3.0.

This means that the real key is embedded inside the computer's BIOS.

Download RWEverything, click on ACPI, and go to tab MSDM.

Your key should be here.

Image

Enjoy your license.

How to install pecl-apd with PHP 5.5 on FreeBSD

Image

This was written on 2014-10-05.

Fetch source (revision was 297236 at the time).

# svn co http://svn.php.net/repository/pecl/apd/trunk

Apply the following patch:

diff --git a/php_apd.c b/php_apd.c
index 9d7f238..3b1fe7e 100644
--- a/php_apd.c
+++ b/php_apd.c
@@ -56,11 +56,19 @@
 #undef TRACE_ZEND_COMPILE /* define to trace all calls to zend_compile_file */
 ZEND_DLEXPORT zend_op_array* apd_compile_file(zend_file_handle* TSRMLS_DC);
 ZEND_DLEXPORT zend_op_array* (*old_compile_file)(zend_file_handle* TSRMLS_DC);
+#if PHP_VERSION_ID < 50500
 ZEND_DLEXPORT void apd_execute(zend_op_array *op_array TSRMLS_DC);
 #if  ZEND_EXTENSION_API_NO >= 20020731
 ZEND_DLEXPORT void apd_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
 #endif
 ZEND_DLEXPORT void (*old_execute)(zend_op_array *op_array TSRMLS_DC);
+#else
+ZEND_DLEXPORT void apd_execute_ex(zend_execute_data *execute_data TSRMLS_DC);
+#if  ZEND_EXTENSION_API_NO >= 20020731
+ZEND_DLEXPORT void apd_execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC);
+#endif
+ZEND_DLEXPORT void (*old_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);
+#endif
 
 ZEND_DLEXPORT void onStatement(zend_op_array *op_array);
 ZEND_DECLARE_MODULE_GLOBALS(apd);
@@ -337,7 +345,7 @@ char *apd_get_active_function_name(zend_op_array *op_array TSRMLS_DC)
 			}
 		} 
 		else {
-			switch (execd->opline->op2.u.constant.value.lval) {
+			switch (execd->opline->extended_value) {
 			case ZEND_EVAL:
 				funcname = estrdup("eval");
 				break;
@@ -441,8 +449,8 @@ static void log_time(TSRMLS_D)
 		if(utime || stime || rtime) {
             int lineno = 0;
             if(EG(active_op_array)) {
-				if(EG(active_op_array)->start_op) {
-					lineno = EG(active_op_array)->start_op->lineno;
+				if(EG(start_op)) {
+					lineno = EG(start_op)->lineno;
 				} else if(EG(active_op_array)->opcodes) {
 					lineno = EG(active_op_array)->opcodes->lineno;
 				}
@@ -510,28 +518,46 @@ PHP_MINIT_FUNCTION(apd)
 {
 	ZEND_INIT_MODULE_GLOBALS(apd, php_apd_init_globals, NULL)
 	REGISTER_INI_ENTRIES();
+
+#if PHP_VERSION_ID < 50500
 	old_execute = zend_execute;
 	zend_execute = apd_execute;
+#else
+	old_execute_ex = zend_execute_ex;
+	zend_execute_ex = apd_execute_ex;
+#endif
+
 	zend_execute_internal = apd_execute_internal;
 	return SUCCESS;
 }
 
-
-ZEND_API void apd_execute(zend_op_array *op_array TSRMLS_DC) 
-{
+#if PHP_VERSION_ID < 50500
+ZEND_DLEXPORT void apd_execute (zend_op_array *op_array TSRMLS_DC) {
+#else
+ZEND_DLEXPORT void apd_execute_ex (zend_execute_data *execute_data TSRMLS_DC) {
+  zend_op_array *op_array = execute_data->op_array;
+#endif
 	char *fname = NULL;
 	
   	fname = apd_get_active_function_name(op_array TSRMLS_CC);
    	trace_function_entry(EG(function_table), fname, ZEND_USER_FUNCTION,
 						zend_get_executed_filename(TSRMLS_C),
 						EG(in_execution)?zend_get_executed_lineno(TSRMLS_C):0);
-   	old_execute(op_array TSRMLS_CC);
+#if PHP_VERSION_ID < 50500
+    old_execute(op_array TSRMLS_CC);
+#else
+    old_execute_ex(execute_data TSRMLS_CC);
+#endif
    	trace_function_exit(fname);
    	efree(fname);
 	apd_interactive();
 }
 
+#if PHP_VERSION_ID < 50500
 ZEND_API void apd_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) 
+#else
+ZEND_API void apd_execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC) 
+#endif
 {
 	char *fname = NULL;
 	zend_execute_data *execd;
@@ -541,7 +567,11 @@ ZEND_API void apd_execute_internal(zend_execute_data *execute_data_ptr, int retu
    	trace_function_entry(EG(function_table), fname, ZEND_INTERNAL_FUNCTION,
 						zend_get_executed_filename(TSRMLS_C),
 						EG(in_execution)?zend_get_executed_lineno(TSRMLS_C):0);
-	execute_internal(execute_data_ptr, return_value_used TSRMLS_CC);
+#if PHP_VERSION_ID < 50500
+    execute_internal(execute_data_ptr, return_value_used TSRMLS_CC);
+#else
+    execute_internal(execute_data_ptr, fci, return_value_used TSRMLS_CC);
+#endif
 	trace_function_exit(fname);
 	efree(fname);
 	apd_interactive();

If you don't, you'll have the following error output:

 cc -I. -I/root/apdgit/apd2/trunk -DPHP_ATOM_INC -I/root/apdgit/apd2/trunk/include -I/root/apdgit/apd2/trunk/main -I/root/apdgit/apd2/trunk -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /root/apdgit/apd2/trunk/php_apd.c  -fPIC -DPIC -o .libs/php_apd.o
/root/apdgit/apd2/trunk/php_apd.c:206:36: warning: format string is not a string literal (potentially insecure)
      [-Wformat-security]
                fprintf(APD_GLOBALS(pprof_file), newStr);
                                                 ^~~~~~
/root/apdgit/apd2/trunk/php_apd.c:318:12: warning: assigning to 'char *' from 'const char *' discards qualifiers
      [-Wincompatible-pointer-types-discards-qualifiers]
                tmpfname = execd->function_state.function->common.function_name;
                         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/apdgit/apd2/trunk/php_apd.c:322:15: warning: assigning to 'char *' from 'const char *' discards qualifiers
      [-Wincompatible-pointer-types-discards-qualifiers]
                                classname = Z_OBJCE(*execd->object)->name;
                                          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/apdgit/apd2/trunk/php_apd.c:329:15: warning: assigning to 'char *' from 'const char *' discards qualifiers
      [-Wincompatible-pointer-types-discards-qualifiers]
                                classname = execd->function_state.function->common.scope->name;
                                          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/apdgit/apd2/trunk/php_apd.c:340:31: error: no member named 'u' in 'union _znode_op'
                        switch (execd->opline->op2.u.constant.value.lval) {
                                ~~~~~~~~~~~~~~~~~~ ^
/root/apdgit/apd2/trunk/php_apd.c:444:29: error: no member named 'start_op' in 'struct _zend_op_array'
                                if(EG(active_op_array)->start_op) {
                                   ~~~~~~~~~~~~~~~~~~~  ^
/root/apdgit/apd2/trunk/php_apd.c:445:36: error: no member named 'start_op' in 'struct _zend_op_array'
                                        lineno = EG(active_op_array)->start_op->lineno;
                                                 ~~~~~~~~~~~~~~~~~~~  ^
/root/apdgit/apd2/trunk/php_apd.c:506:35: warning: 'memset' call operates on objects of type 'zend_apd_globals'
      (aka 'struct _zend_apd_globals') while the size is based on a different type 'zend_apd_globals *'
      (aka 'struct _zend_apd_globals *') [-Wsizeof-pointer-memaccess]
    memset(apd_globals, 0, sizeof(apd_globals));
           ~~~~~~~~~~~            ^~~~~~~~~~~
/root/apdgit/apd2/trunk/php_apd.c:506:35: note: did you mean to dereference the argument to 'sizeof' (and multiply it
      by the number of elements)?
    memset(apd_globals, 0, sizeof(apd_globals));
                                  ^~~~~~~~~~~
/root/apdgit/apd2/trunk/php_apd.c:514:15: error: non-object type 'void (zend_op_array *)' is not assignable
        zend_execute = apd_execute;
        ~~~~~~~~~~~~ ^
/root/apdgit/apd2/trunk/php_apd.c:515:24: warning: incompatible pointer types assigning to 'void
      (*)(zend_execute_data *, struct _zend_fcall_info *, int)' from 'void (zend_execute_data *, int)'
      [-Wincompatible-pointer-types]
        zend_execute_internal = apd_execute_internal;
                              ^ ~~~~~~~~~~~~~~~~~~~~
/root/apdgit/apd2/trunk/php_apd.c:544:64: error: too few arguments to function call, expected 3, have 2
        execute_internal(execute_data_ptr, return_value_used TSRMLS_CC);
        ~~~~~~~~~~~~~~~~                                              ^
/usr/local/include/php/Zend/zend_execute.h:62:1: note: 'execute_internal' declared here
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_...
^
/usr/local/include/php/main/../main/php_config.h:6:19: note: expanded from macro 'ZEND_API'
# define ZEND_API __attribute__ ((visibility("default")))
                  ^
/root/apdgit/apd2/trunk/php_apd.c:724:11: warning: assigning to 'char *' from 'const char *' discards qualifiers
      [-Wincompatible-pointer-types-discards-qualifiers]
        filename = zend_get_executed_filename(TSRMLS_C);
                 ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 warnings and 5 errors generated.
*** Error code 1

Configure and build:

# phpize
# ./configure
# make

Install:

# make install

Load:

zend_extension = "/usr/local/lib/php/20121212/apd.so"
apd.dumpdir="/var/tmp/apd"

Check:

# php -v
PHP 5.5.13 (cli) (built: Jun 11 2014 11:54:41)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies
    with Xdebug v2.2.5, Copyright (c) 2002-2014, by Derick Rethans
    with Advanced PHP Debugger (APD) v1.0.2-dev, , by George Schlossnagle

You'll find patched version of the project here:
Github: ZeWaren/pecl-apd (https://github.com/ZeWaren/pecl-apd).

How to create a certificate to send APNS notifications, manually using OpenSSL

Image

Create your key.

openssl genrsa -out truc.example.org.key 2048

Create the certificate request:

openssl req -new -key truc.example.org.key -out truc.example.org.csr

Upload the CSR to Apple, and get the resultant certificate.

Optionally convert the certificate to PEM format.

openssl x509 -inform der -in truc.example.org.cer -out truc.example.org.crt.pem

Check if you can connect to APNS with your credentials:

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert truc.example.org.crt.pem -key truc.example.org.key

Use the key and certificate files for profit.

How to add HTTP Authorization to Synology's web interface

Image

Situation

This article is relevant to a DS412+ appliance.

You're using a small Synology server. You use the web interface for whatever purpose. (the one at http://nas.example.com:5001). You'd like to access this interface remotely, but you are afraid to open the port on your firewall since you don't trust the associated CGI scripts.

Solution

Add HTTP auth to httpd, so that any request must go through a password.

Create file /usr/syno/etc/httpd/passwd (here or in whatever location you fancy) and create your credential database.

user:$apr1$mN37yOqk$7wKJq7B710AcJSa7Y6WJD1
user2:$apr1$4zha9SDn$Vcs481LpfkUMx1Y/SybKw.
user3:$apr1$Gq/AeNY4$68DGcCVo6BdOSy1eSDjkP/
user4:$apr1$ihJ0/hfG$1MUZzj3LYKG7tU3P7S9hh/

Create file /etc/httpd/conf/extra/httpd-something.conf and configure httpd to serve on port 5002 the same content as port 5001, but with basic HTTP authentication.

Listen 5002

LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authn_file_module modules/mod_authn_file.so

<VirtualHost *:5002>
    ServerName *
    ServerAlias *

    SSLEngine on

    <Location />
        AuthType Basic
        AuthName "Secure Content"
        AuthBasicProvider file
        AuthUserFile /usr/syno/etc/httpd/passwd
        Require valid-user
    </Location>
</VirtualHost>

Edit /etc/httpd/conf/httpd.conf-sys and include the preceding file at the end.

Include conf/extra/httpd-something.conf

Restart httpd.

/usr/syno/etc/rc.d/S97apache-sys.sh restart

Forward port 5002 in your firewall.

Image

Enjoy your (a tiny bit more) secured NAS from anywhere in the world.

Building an OTP release including Lager with rebar and reltool

Image

Building an OTP release including Lager with rebar and reltool.

Create your app the usual way:

rebar create-app appid=testapplager

Add the following to rebar.config:

{lib_dirs,["deps"]}.
{sub_dirs, ["rel"]}.
{deps, [
    {lager, ".*", {
        git, "git://github.com/basho/lager.git", "master"}
    }
]}.
{erl_opts, [{parse_transform, lager_transform}]}.

Add some code to your app, get the dependencies and compile.

rebar get-deps
rebar compile

Create a node configuration

mkdir rel && cd rel
rebar create-node nodeid=testapplager

Set the different paths to the dependencies and your app in reltool.config:

{sys, [
       {lib_dirs, ["../deps"]},
       {erts, [{mod_cond, derived}, {app_file, strip}]},
       {app_file, strip},
       {rel, "testapplager", "1",
        [
         kernel,
         stdlib,
         sasl,
         lager,
         testapplager
        ]},
       {rel, "start_clean", "",
        [
         kernel,
         stdlib
        ]},
       {boot_rel, "testapplager"},
       {profile, embedded},
       {incl_cond, exclude},
       {excl_archive_filters, [".*"]}, %% Do not archive built libs
       {excl_sys_filters, ["^bin/.*", "^erts.*/bin/(dialyzer|typer)",
                           "^erts.*/(doc|info|include|lib|man|src)"]},
       {excl_app_filters, ["\.gitignore"]},
       {app, sasl,   [{incl_cond, include}]},
       {app, stdlib, [{incl_cond, include}]},
       {app, kernel, [{incl_cond, include}]},
       {app, lager, [{incl_cond, include}]},
       {app, testapplager, [{mod_cond, app}, {incl_cond, include}, {lib_dir, ".."}]}
      ]}.

{target_dir, "testapplager"}.

{overlay, [
           {mkdir, "log/sasl"},
           {copy, "files/erl", "\{\{erts_vsn\}\}/bin/erl"},
           {copy, "files/nodetool", "\{\{erts_vsn\}\}/bin/nodetool"},
           {copy, "files/testapplager", "bin/testapplager"},
           {copy, "files/testapplager.cmd", "bin/testapplager.cmd"},
           {copy, "files/start_erl.cmd", "bin/start_erl.cmd"},
           {copy, "files/install_upgrade.escript", "bin/install_upgrade.escript"},
           {copy, "files/sys.config", "releases/\{\{rel_vsn\}\}/sys.config"},
           {copy, "files/vm.args", "releases/\{\{rel_vsn\}\}/vm.args"}
          ]}.

Try to build the release:

rebar generate

Failure!

ERROR: generate failed while processing /root/some-sub-folder/testapplager/rel: {'EXIT',{{badmatch,{error,"Application compiler is used in release \"testapplager\" and cannot be excluded"}},
         [{rebar_reltool,generate,2,
                         [{file,"src/rebar_reltool.erl"},{line,50}]},
          {rebar_core,run_modules,4,[{file,"src/rebar_core.erl"},{line,425}]},
          {rebar_core,execute,5,[{file,"src/rebar_core.erl"},{line,359}]},
          {rebar_core,process_dir0,6,[{file,"src/rebar_core.erl"},{line,223}]},
          {rebar_core,process_dir,4,[{file,"src/rebar_core.erl"},{line,130}]},
          {rebar_core,process_each,5,[{file,"src/rebar_core.erl"},{line,296}]},
          {rebar_core,process_dir0,6,[{file,"src/rebar_core.erl"},{line,199}]},
          {rebar_core,process_dir,4,
                      [{file,"src/rebar_core.erl"},{line,130}]}]}}

The problem is that reltool won't include any package by default. This means that lager can't get its dependencies built into the release.

To solve this problem, either change the include condition to:

{incl_cond, derived},

Or manually include the dependencies:

       {app, goldrush, [{incl_cond, include}]},
       {app, syntax_tools, [{incl_cond, include}]},
       {app, compiler, [{incl_cond, include}]},

Then rebuild your release.

Xymon's RRD graphs are missing fonts.

Problem

The graphs of your Xymon server suddenly start to be missing their texts. Instead, square lines resembling mojibake appear.

Image

Solution

Reinstalling pango and all its dependencies, then rebuilding xymon-server did the trick.

In my case, I suppose that the font was missing or was not accessible by Xymon anymore.

How to install OpenERP 8 (Odoo) on FreeBSD and run it alongside OpenERP 7.x

ImageImageThe FreeBSD logo

Situation

You're running a nice OpenERP 7.x on one of your favorite FreeBSD server. You'd like to try the new version 8 (Odoo), but you heard about the fact that databases can't be migrated automatically, so you want to run the two versions alongside.

Install version 8

Download and install

These ports should already be installed since you were running openerp-7.x previously. If not, install or upgrade them:

/graphics/py-imaging
/textproc/py-libxml2
/devel/py-pytz
/lang/py-mx-base
/databases/py-psycopg2
/graphics/py-chart
/graphics/py-pydot
/textproc/py-libxslt
/devel/py-lxml
/textproc/py-xml
/devel/py-yaml
/textproc/py-mako
/devel/py-dateutil
/print/py-reportlab2

Fetch and extract the release:

fetch 'http://nightly.odoo.com/8.0/nightly/src/odoo_8.0rc1-latest.tar.gz'
tar xzvf odoo_8.0rc1-latest.tar.gz
cd openerp-8.0rc1

Install the release

python setup.py install

Warning: this setup will install python packages itself without using the port tree. This is not optimal but it should work quite well anyway.

I recommend installing Odoo in a jail so that you don't trash your entire superb production system.

Set the permissions on the install folder:

chown -R openerpd:wheel /usr/local/lib/python2.7/site-packages/openerp-8.0rc1-py2.7.egg/

Create the configuration files

Theses configuration files might include some useless fields or some things that aren't supported anymore. Use them at your own risks.

/usr/local/etc/openerp-server.conf:

[options]
# Basic daemon configuration options ##################
root_path = /usr/local/lib/python2.7/site-packages/openerp-8.0rc1-py2.7.egg
addons_path = /usr/local/lib/python2.7/site-packages/openerp-8.0rc1-py2.7.egg/openerp/addons
# netinterface =
# interface =
xmlrpc_interface =
xmlrpc_port = 8169
debug_mode = False
stop_after_init = False
soap = False
xmlrpc = True
netrpc = True
netrpc_interface =
netrpc_port = 8070
secure = False
cache_timeout = 100000
pidfile = /var/run/openerp/openerp-server.pid
reportgz = False
admin_passwd = admin
login_message = False
price_accuracy = 2
csv_internal_sep = ,
translate_modules = ['all']

# Logging options #####################################
syslog = False
log_level = info
logfile = /var/log/openerp/openerp-server.log
assert_exit_level = warn

# Database options ####################################
db_name = openerp
db_user = openerp
db_password = openerppassword
db_host = localhost
db_maxconn = 64
pg_path = /usr/local/bin
list_db = True
# import_partial =

# SMTP options ########################################
smtp_server = localhost
smtp_port = 25
smtp_user = False
smtp_password = False
email_from = False

# Use demo files? #####################################
# without_demo = True
# demo = {}

/usr/local/etc/openerp-web.conf:

# Example configuration file for OpenERP-web
#
# This is an example configuration file, just copy it
# to openerp-web.conf and edit it to suit your needs.

# OpenERP Web server
[global]

# the ip and port the web server will be listening on
server.socket_host = "0.0.0.0" # 0.0.0.0 means all ip addresses
server.socket_port = 8180

# Sets the number of threads the server uses
server.thread_pool = 10

server.environment = "development"

# Simple code profiling
server.profile_on = False
server.profile_dir = "profile"

# Set to True if you are deploying your App behind a proxy
# e.g. Apache using mod_proxy
#tools.proxy.on = True

# If your proxy does not add the X-Forwarded-Host header, set
# the following to the *public* host url.
#tools.proxy.base = 'http://mydomain.com'

# logging
log.access_file = "/var/log/openerp-web/access.log"
log.error_file = "/var/log/openerp-web/error.log"

# OpenERP Server information
[openerp]
host = 'localhost'
port = '8170'
protocol = 'socket'

# Web client settings
[openerp-web]
# filter dblists based on url pattern?
# NONE: No Filter
# EXACT: Exact Hostname
# UNDERSCORE: Hostname_
# BOTH: Exact Hostname or Hostname_

dblist.filter = 'NONE'

# whether to show Databases button on Login screen or not
dbbutton.visible = True

# will be applied on company logo
company.url = ''

# options to limit data rows in M2M/O2M lists, will be overriden
# with limit="5", min_rows="5" attributes in the tree view definitions
child.listgrid.limit = 5
child.listgrid.min_rows = 5

Don't forget to do what's needed to allow user openerpd to write its log files.

Create the RC scripts

Don't forget to chmod them so they can be executed.

/usr/local/etc/rc.d/openerp-server:

#!/bin/sh
#
# PROVIDE: openerpd
# REQUIRE: postgresql LOGIN
#
# Add the following lines to /etc/rc.conf to enable openerp-server
#
#
# openerpd_enable (bool): Set to "NO" by default,
#                         Set it to "YES" to enable openerp-server
#
# openerpd_config (str):  The path to the openerp-server configuration file
#                         (defaults to /usr/local/etc/openerp-server.conf)
#
# openerpd_flags (str):   Extra arguments to be used when invoking
#                         the openerp-server daemon.
#
# Patch submitted by (c) Franck Porcher, Ph.D, to fix some issues regarding
# pidfile, log files, and discrepencies with the main configuration file.

#  getval varname file [default_value] [separator_char]
#  - Discard comment lines (any text leading with blanks then #)
#  - Retain only the last value set


. /etc/rc.subr

name=openerpd
command=/usr/local/bin/openerp-server
rcvar=openerpd_enable

load_rc_config $name

openerpd_enable="${openerpd_enable-"NO"}"
openerpd_config="${openerpd_config-"/usr/local/etc/openerp-server.conf"}"
openerpd_user="${openerpd_user-"openerpd"}"
openerpd_pidfile="${openerpd_pidfile:-"$(grep pidfile /usr/local/etc/openerp-server.conf | awk -F "=" ' { print $2 } ' |sed 's/[ ]//g' )"}"
openerpd_logdir="${openerpd_logdir:-"$(dirname `grep logfile /usr/local/etc/openerp-server.conf | awk -F "=" ' { print $2 } ' `)"}"
openerpd_flags="${openerpd_flags:-"--config=${openerpd_config}"}"

# /etc/rc.subr use $pidfile (not ${name}_pidfile)
pidfile="${openerpd_pidfile}"

required_files="${openerpd_config}"

start_precmd="${name}_prestart"
stop_cmd="${name}_stop"
status_cmd="${name}_status"
getval_cmd="${name}_getval"

openerpd_prestart()
{
    local d

    d="$(dirname "${openerpd_pidfile}")"
    if [ ! -d "${d}" ]
    then
        mkdir -p "${d}"
    fi
    chown "${openerpd_user}" "${d}"

    d="$openerpd_logdir"
    if [ ! -d "${d}" ]
    then
        mkdir -p "${d}"
    fi
    chown "${openerpd_user}" "${d}"
}

openerpd_stop()
{
    # echo "Looking for (openerp-server ${openerpd_flags})"
    openerpd_pid=$(pgrep -f "openerp-server ${openerpd_flags}")
    # Try its best to stop the service
    if [ -f "${openerpd_pidfile}" ] && [ "${openerpd_pidfile}" = "${openerpd_pid}" ]
    then
        echo "Stopping ${name}."
        kill -15 "$(cat "${openerpd_pidfile}")"
    else
        if [ -n "${openerpd_pid}" ]
        then
            echo "Stopping ${name}."
            kill -15 "${openerpd_pid}"
        else
            echo "${name} not running? (pidfile not found)"
        fi
    fi
}

openerpd_status()
{
    # Try its best to find the service's status
    if [ -f "${openerpd_pidfile}" ]
    then
        openerpd_pid="$(cat "${openerpd_pidfile}")"
    fi

    if [ -z "${openerpd_pid}" ]
    then
    openerpd_pid=$(pgrep -f "openerp-server.py ${openerpd_flags}")
    [ -n "${openerpd_pid}" ] && echo "${openerpd_pid}" > "${openerpd_pidfile}"
    fi

    if [ -n "${openerpd_pid}" ]
    then
        echo "${name} running with pid: $openerpd_pid"
    else
        echo "${name} not running? (pid not found)"
    fi
}

command_args=" >/dev/null 2>&1 &"

load_rc_config $name
run_rc_command "$1"

/etc/rc.conf:

openerpd_enable="YES"
openerpweb_enable="YES"
openerpweb_user="openerpd"

/usr/local/bin/openerp-server:

#!/usr/local/bin/python
# EASY-INSTALL-SCRIPT: 'openerp==8.0rc1','openerp-server'
import os
os.environ['PYTHON_EGG_CACHE'] = '/home/openerpd/.python-eggs'
os.environ['XDG_DATA_HOME'] = '/home/openerpd/.local'
__requires__ = 'openerp==8.0rc1'
import pkg_resources
pkg_resources.run_script('openerp==8.0rc1', 'openerp-server')

Start the server

/usr/local/etc/rc.d/openerp-server start

If the server does not start, try to start it manually and look for any output:

su -m openerpd -c 'sh -c "/usr/local/bin/openerp-server --config=/usr/local/etc/openerp-server.conf"'

Run OpenERP 7.x at the same time

Install OpenERP 7.x the same way as version 8, or using port finance/openerp-server.

Create the configuration files

Makes sure that the two version listen on different ports.

/usr/local/etc/openerp-server7.conf:

[options]
# Basic daemon configuration options ##################
root_path = /usr/local/lib/python2.7/site-packages/openerp-server/
addons_path = /usr/local/lib/python2.7/site-packages/openerp-7.0_20130917_231058-py2.7.egg/openerp/addons
# netinterface =
# interface =
port = 8069
netport = 8070
debug_mode = False
stop_after_init = False
soap = False
xmlrpc = True
netrpc = True
secure = False
cache_timeout = 100000
pidfile = /var/run/openerp/openerp-server7.pid
reportgz = False
admin_passwd = admin
login_message = False
price_accuracy = 2
csv_internal_sep = ,
translate_modules = ['all']

# Logging options #####################################
syslog = False
log_level = info
logfile = /var/log/openerp/openerp-server7.log
assert_exit_level = warn

# Database options ####################################
db_name = openerp
db_user = openerp
db_password = openerppassword
db_host = localhost
db_maxconn = 64
pg_path = /usr/local/bin
list_db = True
# import_partial =

# SMTP options ########################################
smtp_server = localhost
smtp_port = 25
smtp_user = False
smtp_password = False
email_from = False

# Use demo files? #####################################
# without_demo = True
# demo = {}

/usr/local/etc/openerp-web7.conf:

# Example configuration file for OpenERP-web
#
# This is an example configuration file, just copy it
# to openerp-web.conf and edit it to suit your needs.

# OpenERP Web server
[global]

# the ip and port the web server will be listening on
server.socket_host = "0.0.0.0" # 0.0.0.0 means all ip addresses
server.socket_port = 8180

# Sets the number of threads the server uses
server.thread_pool = 10

server.environment = "development"

# Simple code profiling
server.profile_on = False
server.profile_dir = "profile"

# Set to True if you are deploying your App behind a proxy
# e.g. Apache using mod_proxy
#tools.proxy.on = True

# If your proxy does not add the X-Forwarded-Host header, set
# the following to the *public* host url.
#tools.proxy.base = 'http://mydomain.com'

# logging
log.access_file = "/var/log/openerp-web/access7.log"
log.error_file = "/var/log/openerp-web/error7.log"

# OpenERP Server information
[openerp]
host = 'localhost'
port = '8170'
protocol = 'socket'

# Web client settings
[openerp-web]
# filter dblists based on url pattern?
# NONE: No Filter
# EXACT: Exact Hostname
# UNDERSCORE: Hostname_
# BOTH: Exact Hostname or Hostname_

dblist.filter = 'NONE'

# whether to show Databases button on Login screen or not
dbbutton.visible = True

# will be applied on company logo
company.url = ''

# options to limit data rows in M2M/O2M lists, will be overriden
# with limit="5", min_rows="5" attributes in the tree view definitions
child.listgrid.limit = 5
child.listgrid.min_rows = 5

Create the RC scripts

/usr/local/etc/rc.d/openerp-server7:

#!/bin/sh
#
# PROVIDE: openerpd7
# REQUIRE: postgresql LOGIN
#
# Add the following lines to /etc/rc.conf to enable openerp-server
#
#
# openerpd7_enable (bool): Set to "NO" by default,
#                         Set it to "YES" to enable openerp-server
#
# openerpd7_config (str):  The path to the openerp-server configuration file
#                         (defaults to /usr/local/etc/openerp-server.conf)
#
# openerpd7_flags (str):   Extra arguments to be used when invoking
#                         the openerp-server daemon.
#
# Patch submitted by (c) Franck Porcher, Ph.D, to fix some issues regarding
# pidfile, log files, and discrepencies with the main configuration file.

#  getval varname file [default_value] [separator_char]
#  - Discard comment lines (any text leading with blanks then #)
#  - Retain only the last value set


. /etc/rc.subr

name=openerpd7
command=/usr/local/bin/openerp-server7
rcvar=openerpd7_enable

load_rc_config $name

openerpd7_enable="${openerpd7_enable-"NO"}"
openerpd7_config="${openerpd7_config-"/usr/local/etc/openerp-server7.conf"}"
openerpd7_user="${openerpd7_user-"openerpd"}"
openerpd7_pidfile="${openerpd7_pidfile:-"$(grep pidfile /usr/local/etc/openerp-server7.conf | awk -F "=" ' { print $2 } ' |sed 's/[ ]//g' )"}"
openerpd7_logdir="${openerpd7_logdir:-"$(dirname `grep logfile /usr/local/etc/openerp-server7.conf | awk -F "=" ' { print $2 } ' `)"}"
openerpd7_flags="${openerpd7_flags:-"--config=${openerpd7_config}"}"

# /etc/rc.subr use $pidfile (not ${name}_pidfile)
pidfile="${openerpd7_pidfile}"

required_files="${openerpd7_config}"

start_precmd="${name}_prestart"
stop_cmd="${name}_stop"
status_cmd="${name}_status"
getval_cmd="${name}_getval"

openerpd7_prestart()
{
    local d

    d="$(dirname "${openerpd7_pidfile}")"
    if [ ! -d "${d}" ]
    then
        mkdir -p "${d}"
    fi
    chown "${openerpd7_user}" "${d}"

    d="$openerpd7_logdir"
    if [ ! -d "${d}" ]
    then
        mkdir -p "${d}"
    fi
    chown "${openerpd7_user}" "${d}"
}

openerpd7_stop()
{
    # echo "Looking for (openerp-server ${openerpd7_flags})"
    openerpd7_pid=$(pgrep -f "openerp-server ${openerpd7_flags}")
    # Try its best to stop the service
    if [ -f "${openerpd7_pidfile}" ] && [ "${openerpd7_pidfile}" = "${openerpd7_pid}" ]
    then
        echo "Stopping ${name}."
        kill -15 "$(cat "${openerpd7_pidfile}")"
    else
        if [ -n "${openerpd7_pid}" ]
        then
            echo "Stopping ${name}."
            kill -15 "${openerpd7_pid}"
        else
            echo "${name} not running? (pidfile not found)"
        fi
    fi
}

openerpd7_status()
{
    # Try its best to find the service's status
    if [ -f "${openerpd7_pidfile}" ]
    then
        openerpd7_pid="$(cat "${openerpd7_pidfile}")"
    fi

    if [ -z "${openerpd7_pid}" ]
    then
    openerpd7_pid=$(pgrep -f "openerp-server.py ${openerpd7_flags}")
    [ -n "${openerpd7_pid}" ] && echo "${openerpd7_pid}" > "${openerpd7_pidfile}"
    fi

    if [ -n "${openerpd7_pid}" ]
    then
        echo "${name} running with pid: $openerpd7_pid"
    else
        echo "${name} not running? (pid not found)"
    fi
}


command_args=" >/dev/null 2>&1 &"

load_rc_config $name
run_rc_command "$1"

/etc/rc.conf:

openerpd7_enable="YES"
openerpweb7_enable="YES"
openerpweb7_user="openerpd"

/usr/local/bin/openerp-server7:

#!/usr/local/bin/python
# EASY-INSTALL-SCRIPT: 'openerp==7.0-20130917-231058','openerp-server'
import os
os.environ['PYTHON_EGG_CACHE'] = '/tmp/python_egg_cache'
__requires__ = 'openerp==7.0-20130917-231058'
import pkg_resources
pkg_resources.run_script('openerp==7.0-20130917-231058', 'openerp-server')

Start the server

/usr/local/etc/rc.d/openerp-server7 start

If the server does not start, try to start it manually and look for any output:

su -m openerpd -c 'sh -c "/usr/local/bin/openerp-server7 --config=/usr/local/etc/openerp-server7.conf"'

How to download only one Android source code project using repo

Image

Situation

You want to submit a small patch to an Android source project.

You don't want to download the entire 14GB Android source code.

What you did

Initialize repo.

repo init -u https://android.googlesource.com/platform/manifest
Get https://gerrit.googlesource.com/git-repo
remote: Counting objects: 117, done
remote: Finding sources: 100% (117/117)
remote: Total 2879 (delta 1523), reused 2879 (delta 1523)
Receiving objects: 100% (2879/2879), 2.44 MiB | 696 KiB/s, done.
Resolving deltas: 100% (1523/1523), done.
From https://gerrit.googlesource.com/git-repo
 * [new branch]      maint      -> origin/maint
 * [new branch]      master     -> origin/master
 * [new branch]      stable     -> origin/stable
 * [new tag]         v1.0       -> v1.0
 * [new tag]         v1.0.1     -> v1.0.1
[...]
Get https://android.googlesource.com/platform/manifest
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (22) The requested URL returned error: 404 Not Found
Server does not provide clone.bundle; ignoring.
remote: Counting objects: 110, done
remote: Finding sources: 100% (110/110)
remote: Total 1345 (delta 288), reused 1345 (delta 288)
Receiving objects: 100% (1345/1345), 1.13 MiB | 479 KiB/s, done.
Resolving deltas: 100% (288/288), done.
From https://android.googlesource.com/platform/manifest
[...]
 * [new tag]         android-sdk-support_r11 -> android-sdk-support_r11

Your Name  [U-dl_muriers_em\ZWM]: Erwan Martin
Your Email [ZWM@dl_muriers_em.(none)]: public@fzwte.net

Your identity is: Erwan Martin <public@fzwte.net>
is this correct [y/N]? y

repo has been initialized in /home/ZWM

Sync the project.

repo sync platform/tools/base
Traceback (most recent call last):
  File "/home/ZWM/.repo/repo/main.py", line 500, in <module>
    _Main(sys.argv[1:])
  File "/home/ZWM/.repo/repo/main.py", line 476, in _Main
    result = repo._Run(argv) or 0
  File "/home/ZWM/.repo/repo/main.py", line 155, in _Run
    result = cmd.Execute(copts, cargs)
  File "/home/ZWM/.repo/repo/subcmds/sync.py", line 624, in Execute
    submodules_ok=opt.fetch_submodules)
  File "/home/ZWM/.repo/repo/command.py", line 184, in GetProjects
    raise InvalidProjectGroupsError(arg)
error.InvalidProjectGroupsError

InvalidProjectGroupsError? Whaaaaaat!?

Why did that happen

Let's open .repo/repo/command.py and go where the command failed.

        for project in projects:
          if not missing_ok and not project.Exists:
            raise NoSuchProjectError(arg)
          if not project.MatchesGroups(groups):
            raise InvalidProjectGroupsError(arg)

Apparently, a notion of group exists. Let's open the manifest and see in what group our project is.

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  [...]
  <project path="tools/base" name="platform/tools/base" groups="notdefault,tools" />
</manifest>

notdefault? That doesn't sound good.

What you should have done

Init repo including group tools.

repo init -u https://android.googlesource.com/platform/manifest -g tools
[...]

Sync the project.

repo sync platform/tools/base
Fetching project platform/tools/base
[...]
Fetching projects: 100% (1/1), done.
Checking out files: 100% (5614/5614), done.

Create and checkout your branch.

repo start your-local-branch-name platform/tools/base

Work your magic and upload your changes.

repo upload

Reference

Syndicate content