Commit 4dcd2da6 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

Merge remote-tracking branch 'origin/master' into erp5-cluster

parents 9e801ac2 37e82517
# GNU C Compiler # GNU C Compiler
# Mostly required to support languages different then C or C++ # Mostly required to support languages different than C or C++
[buildout] [buildout]
extends = extends =
../m4/buildout.cfg ../m4/buildout.cfg
......
...@@ -19,10 +19,10 @@ parts = ...@@ -19,10 +19,10 @@ parts =
[mariadb] [mariadb]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
version = 10.0.9 version = 10.0.10
revision = 1 revision = 1
url = http://downloads.askmonty.org/f/mariadb-${:version}/kvm-tarbake-jaunty-x86/mariadb-${:version}.tar.gz/from/http://ftp.osuosl.org/pub/mariadb url = http://downloads.askmonty.org/f/mariadb-${:version}/kvm-tarbake-jaunty-x86/mariadb-${:version}.tar.gz/from/http://ftp.osuosl.org/pub/mariadb
md5sum = 36363eaaeace9e81a64ac94d9d53bffe md5sum = 14ce22b8197d4eae88d237776d47220f
# compile directory is required to build mysql plugins. # compile directory is required to build mysql plugins.
keep-compile-dir = true keep-compile-dir = true
patch-options = -p0 patch-options = -p0
...@@ -58,6 +58,9 @@ environment = ...@@ -58,6 +58,9 @@ environment =
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = http://packages.groonga.org/source/mroonga/mroonga-4.01.tar.gz url = http://packages.groonga.org/source/mroonga/mroonga-4.01.tar.gz
md5sum = 7081aed69e715fb4b0b8f65b0d8d99f1 md5sum = 7081aed69e715fb4b0b8f65b0d8d99f1
patch-options = -p1
patches =
${:_profile_base_location_}/mroonga-4.01-mariadb-10.0.10.patch#f229aca89b6223c43add5f2bd5f5d359
configure-options = configure-options =
--with-mysql-source=${mariadb:location}__compile__/mariadb-${mariadb:version} --with-mysql-source=${mariadb:location}__compile__/mariadb-${mariadb:version}
--with-mysql-config=${mariadb:location}/bin/mysql_config --with-mysql-config=${mariadb:location}/bin/mysql_config
......
commit e2d340aa5eff721eaff24003a3d04eb01f0aaa3c
Author: Kouhei Sutou <kou@clear-code.com>
Date: Sat Mar 15 17:47:08 2014 +0900
mariadb: support MariaDB 10.0.9
Redmine: fixes #2387
We drop MariaDB 10.0.0 - 10.0.8 support. You should use the latest
MariaDB for 10.0 series.
Reported by Kazuhiko Shiozaki. Thanks!!!
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 496deed..3310a16 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -182,6 +182,13 @@ else()
set_mysql_config_value("--version" MYSQL_VERSION)
endif()
+if((${MYSQL_VERSION} VERSION_GREATER "10.0.0") AND
+ (${MYSQL_VERSION} VERSION_LESS "10.0.9"))
+ message(FATAL_ERROR
+ "Mroonga doesn't supports MariaDB 10.0.0-10.0.8: <${MYSQL_VERSION}>")
+ return()
+endif()
+
if(MRN_GROONGA_BUNDLED)
set(GROONGA_INCLUDE_DIRS "${MRN_BUNDLED_GROONGA_DIR}/include")
set(GROONGA_LIBRARY_DIRS "${MRN_BUNDLED_GROONGA_DIR}/lib")
diff --git a/mrn_mysql_compat.h b/mrn_mysql_compat.h
index 4dd878b..7312dd7 100644
--- a/mrn_mysql_compat.h
+++ b/mrn_mysql_compat.h
@@ -105,12 +105,11 @@
# define MRN_ITEM_HAVE_ITEM_NAME
#endif
-#if MYSQL_VERSION_ID >= 50500 && \
- !(defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 100004)
+#if MYSQL_VERSION_ID >= 50500 && MYSQL_VERSION_ID < 50700
# define MRN_HAVE_TABLE_DEF_CACHE
#endif
-#if defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 100004
+#if defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 100009
# define MRN_HAVE_TDC_ACQUIRE_SHARE
#endif
diff --git a/mrn_table.cpp b/mrn_table.cpp
index 7a7d4c2..79e1c83 100644
--- a/mrn_table.cpp
+++ b/mrn_table.cpp
@@ -1,7 +1,7 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2011-2013 Kentoku SHIBA
- Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com>
+ Copyright(C) 2011-2014 Kouhei Sutou <kou@clear-code.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -970,7 +970,9 @@ TABLE_SHARE *mrn_get_table_share(TABLE_LIST *table_list, int *error)
hash_value);
#elif defined(MRN_HAVE_TDC_ACQUIRE_SHARE)
share = tdc_acquire_share(thd, table_list->db, table_list->table_name, key,
- key_length, GTS_TABLE, NULL);
+ key_length,
+ table_list->mdl_request.key.tc_hash_value(),
+ GTS_TABLE, NULL);
#else
share = get_table_share(thd, table_list, key, key_length, 0, error);
#endif
diff --git a/ha_mroonga.cpp b/ha_mroonga.cpp
index 20d251a..2504599 100644
--- a/ha_mroonga.cpp
+++ b/ha_mroonga.cpp
@@ -101,22 +101,38 @@
#define MRN_TEXT_SIZE (1 << 16) // 64Kbytes
#define MRN_LONG_TEXT_SIZE (1 << 31) // 2Gbytes
-#if MYSQL_VERSION_ID >= 50500
-# ifdef DBUG_OFF
-# ifndef _WIN32
+#ifdef MRN_HAVE_TDC_LOCK_TABLE_SHARE
+# define mrn_open_mutex(share) &((share)->tdc.LOCK_table_share)
+# define mrn_open_mutex_lock(share) do { \
+ TABLE_SHARE *share_ = share; \
+ if (share_) { \
+ mysql_mutex_lock(mrn_open_mutex(share_)); \
+ } \
+} while (0)
+# define mrn_open_mutex_unlock(share) do { \
+ TABLE_SHARE *share_ = share; \
+ if (share_) { \
+ mysql_mutex_unlock(mrn_open_mutex(share_)); \
+ } \
+} while (0)
+#else
+# if MYSQL_VERSION_ID >= 50500
+# ifdef DBUG_OFF
+# ifndef _WIN32
extern mysql_mutex_t LOCK_open;
+# endif
# endif
-# endif
mysql_mutex_t *mrn_LOCK_open;
-# define mrn_open_mutex_lock() mysql_mutex_lock(mrn_LOCK_open)
-# define mrn_open_mutex_unlock() mysql_mutex_unlock(mrn_LOCK_open)
-#else
-# ifndef _WIN32
+# define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open)
+# define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open)
+# else
+# ifndef _WIN32
extern pthread_mutex_t LOCK_open;
-# endif
+# endif
pthread_mutex_t *mrn_LOCK_open;
-# define mrn_open_mutex_lock()
-# define mrn_open_mutex_unlock()
+# define mrn_open_mutex_lock(share)
+# define mrn_open_mutex_unlock(share)
+# endif
#endif
#if MYSQL_VERSION_ID >= 50600
@@ -1275,13 +1291,15 @@ static int mrn_init(void *p)
mrn_table_def_cache = (HASH *)GetProcAddress(current_module,
"?table_def_cache@@3Ust_hash@@A");
# endif
+# ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE
mrn_LOCK_open =
-# if MYSQL_VERSION_ID >= 50500
+# if MYSQL_VERSION_ID >= 50500
(mysql_mutex_t *)GetProcAddress(current_module,
"?LOCK_open@@3Ust_mysql_mutex@@A");
-# else
+# else
(pthread_mutex_t *)GetProcAddress(current_module,
"?LOCK_open@@3U_RTL_CRITICAL_SECTION@@A");
+# endif
# endif
# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
mrn_table_share_lock_share =
@@ -1297,7 +1315,9 @@ static int mrn_init(void *p)
# ifdef MRN_HAVE_TABLE_DEF_CACHE
mrn_table_def_cache = &table_def_cache;
# endif
+# ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE
mrn_LOCK_open = &LOCK_open;
+# endif
#endif
// init groonga
@@ -3033,10 +3053,10 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
mapper.mysql_table_name(),
TL_WRITE);
#endif
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table->s);
tmp_ref_table_share =
mrn_create_tmp_table_share(&table_list, ref_path, &error);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table->s);
if (!tmp_ref_table_share) {
grn_obj_unlink(ctx, grn_table_ref);
error = ER_CANT_CREATE_TABLE;
@@ -3048,9 +3068,9 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
}
uint ref_pkey_nr = tmp_ref_table_share->primary_key;
if (ref_pkey_nr == MAX_KEY) {
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table->s);
mrn_free_tmp_table_share(tmp_ref_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table->s);
grn_obj_unlink(ctx, grn_table_ref);
error = ER_CANT_CREATE_TABLE;
char err_msg[MRN_BUFFER_SIZE];
@@ -3062,9 +3082,9 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
uint ref_key_parts = KEY_N_KEY_PARTS(ref_key_info);
if (ref_key_parts > 1) {
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table->s);
mrn_free_tmp_table_share(tmp_ref_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table->s);
grn_obj_unlink(ctx, grn_table_ref);
error = ER_CANT_CREATE_TABLE;
char err_msg[MRN_BUFFER_SIZE];
@@ -3076,9 +3096,9 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
}
Field *ref_field = &ref_key_info->key_part->field[0];
if (strcmp(ref_field->field_name, ref_field_name.str)) {
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table->s);
mrn_free_tmp_table_share(tmp_ref_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table->s);
grn_obj_unlink(ctx, grn_table_ref);
error = ER_CANT_CREATE_TABLE;
char err_msg[MRN_BUFFER_SIZE];
@@ -3088,9 +3108,9 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
my_message(error, err_msg, MYF(0));
DBUG_RETURN(false);
}
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table->s);
mrn_free_tmp_table_share(tmp_ref_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table->s);
grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
column = grn_column_create(ctx, table_obj, field->field_name,
strlen(field->field_name),
@@ -4210,18 +4230,18 @@ int ha_mroonga::close()
table_list.init_one_table(mapper.db_name(), mapper.mysql_table_name(),
TL_WRITE);
#endif
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
tmp_table_share =
mrn_create_tmp_table_share(&table_list, share->table_name, &tmp_error);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
if (!tmp_table_share) {
error = tmp_error;
} else if ((tmp_error = alter_share_add(share->table_name,
tmp_table_share))) {
error = tmp_error;
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
mrn_free_tmp_table_share(tmp_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
}
}
bitmap_free(&multiple_column_key_bitmap);
@@ -4394,9 +4414,9 @@ int ha_mroonga::delete_table(const char *name)
table_list.init_one_table(mapper.db_name(), mapper.mysql_table_name(),
TL_WRITE);
#endif
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
tmp_table_share = mrn_create_tmp_table_share(&table_list, name, &error);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
if (!tmp_table_share) {
DBUG_RETURN(error);
}
@@ -4407,9 +4427,9 @@ int ha_mroonga::delete_table(const char *name)
#endif
if (!(tmp_share = mrn_get_share(name, &tmp_table, &error)))
{
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
mrn_free_tmp_table_share(tmp_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
DBUG_RETURN(error);
}
@@ -4425,9 +4445,9 @@ int ha_mroonga::delete_table(const char *name)
tmp_share->long_term_share = NULL;
}
mrn_free_share(tmp_share);
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
mrn_free_tmp_table_share(tmp_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
if (is_temporary_table_name(name)) {
mrn_drop_db(name);
}
@@ -11885,9 +11905,9 @@ int ha_mroonga::rename_table(const char *from, const char *to)
from_mapper.mysql_table_name(),
TL_WRITE);
#endif
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
tmp_table_share = mrn_create_tmp_table_share(&table_list, from, &error);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
if (!tmp_table_share) {
DBUG_RETURN(error);
}
@@ -11897,9 +11917,9 @@ int ha_mroonga::rename_table(const char *from, const char *to)
#endif
if (!(tmp_share = mrn_get_share(from, &tmp_table, &error)))
{
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
mrn_free_tmp_table_share(tmp_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
DBUG_RETURN(error);
}
@@ -11925,9 +11945,9 @@ int ha_mroonga::rename_table(const char *from, const char *to)
} else if (error && from_mapper.table_name()[0] == '#') {
alter_share_add(from, tmp_table_share);
} else {
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(NULL);
mrn_free_tmp_table_share(tmp_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(NULL);
}
DBUG_RETURN(error);
}
@@ -14482,10 +14502,10 @@ char *ha_mroonga::storage_get_foreign_key_create_info()
ref_table_buff,
TL_WRITE);
#endif
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table_share);
tmp_ref_table_share =
mrn_create_tmp_table_share(&table_list, ref_path, &error);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table_share);
if (!tmp_ref_table_share) {
DBUG_RETURN(NULL);
}
@@ -14494,9 +14514,9 @@ char *ha_mroonga::storage_get_foreign_key_create_info()
Field *ref_field = &ref_key_info->key_part->field[0];
append_identifier(ha_thd(), &create_info_str, ref_field->field_name,
strlen(ref_field->field_name));
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table_share);
mrn_free_tmp_table_share(tmp_ref_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table_share);
if (create_info_str.reserve(39)) {
DBUG_RETURN(NULL);
}
@@ -14694,10 +14714,10 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
ref_table_buff,
TL_WRITE);
#endif
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table_share);
tmp_ref_table_share =
mrn_create_tmp_table_share(&table_list, ref_path, &error);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table_share);
if (!tmp_ref_table_share) {
DBUG_RETURN(error);
}
@@ -14709,9 +14729,9 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
strlen(ref_field->field_name),
TRUE);
f_key_info.referenced_fields.push_back(ref_col_name);
- mrn_open_mutex_lock();
+ mrn_open_mutex_lock(table_share);
mrn_free_tmp_table_share(tmp_ref_table_share);
- mrn_open_mutex_unlock();
+ mrn_open_mutex_unlock(table_share);
FOREIGN_KEY_INFO *p_f_key_info =
(FOREIGN_KEY_INFO *) thd_memdup(thd, &f_key_info,
sizeof(FOREIGN_KEY_INFO));
diff --git a/ha_mroonga.hpp b/ha_mroonga.hpp
index 579210e..d200bca 100644
--- a/ha_mroonga.hpp
+++ b/ha_mroonga.hpp
@@ -172,6 +172,10 @@ extern "C" {
# define MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
#endif
+#if (defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 100010)
+# define MRN_HAVE_TDC_LOCK_TABLE_SHARE
+#endif
+
class ha_mroonga;
/* structs */
...@@ -4,8 +4,8 @@ parts = ...@@ -4,8 +4,8 @@ parts =
[pcre] [pcre]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.34.tar.bz2 url = ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.35.tar.bz2
md5sum = 5439e321351bddd5533551bbce128d07 md5sum = 6aacb23986adccd9b3bc626c00979958
configure-options = configure-options =
--disable-static --disable-static
--enable-unicode-properties --enable-unicode-properties
...@@ -127,43 +127,41 @@ MarkupSafe = 0.19 ...@@ -127,43 +127,41 @@ MarkupSafe = 0.19
Werkzeug = 0.9.4 Werkzeug = 0.9.4
cmd2 = 0.6.7 cmd2 = 0.6.7
collective.recipe.template = 1.11 collective.recipe.template = 1.11
itsdangerous = 0.23 itsdangerous = 0.24
lxml = 3.3.3 lxml = 3.3.4
meld3 = 0.6.10 meld3 = 0.6.10
netaddr = 0.7.10 mr.developer = 1.30
prettytable = 0.7.3 netaddr = 0.7.11
prettytable = 0.7.3-nxd001
pyparsing = 2.0.1 pyparsing = 2.0.1
six = 1.6.1 six = 1.6.1
slapos.core = 1.0.3 slapos.core = 1.0.4
slapos.libnetworkcache = 0.13.4 slapos.libnetworkcache = 0.14.1
slapos.recipe.cmmi = 0.2 slapos.recipe.cmmi = 0.2
stevedore = 0.15
xml-marshaller = 0.9.7 xml-marshaller = 0.9.7
z3c.recipe.scripts = 1.0.1 z3c.recipe.scripts = 1.0.1
# Required by: #Required by:
# slapos.core==1.0.3 #slapos.core 1.0.3
Flask = 0.10.1 Flask = 0.10.1
# Required by: #Required by:
# slapos.core==1.0.3 #slapos.core 1.0.3
cliff = 1.5.2 cliff = 1.6.1
# Required by: #Required by:
# slapos.core==1.0.3 #slapos.core 1.0.3
netifaces = 0.8-1 netifaces = 0.8-1
# Required by: #Required by:
# slapos.core==1.0.3 #slapos.core 1.0.3
requests = 2.2.1 requests = 2.2.1
# Required by: #Required by:
# cliff==1.5.2 #slapos.core 1.0.3
stevedore = 0.14.1
# Required by:
# slapos.core==1.0.3
supervisor = 3.0 supervisor = 3.0
# Required by: #Required by:
# slapos.core==1.0.3 #slapos.core 1.0.3
zope.interface = 4.1.0 zope.interface = 4.1.1
...@@ -36,6 +36,7 @@ recipe = zc.recipe.egg ...@@ -36,6 +36,7 @@ recipe = zc.recipe.egg
eggs = eggs =
${lxml-python:egg} ${lxml-python:egg}
slapos.toolbox slapos.toolbox
plone.recipe.command
scripts = scripts =
killpidfromfile killpidfromfile
...@@ -58,7 +59,7 @@ mode = 0644 ...@@ -58,7 +59,7 @@ mode = 0644
[template-apache-frontend] [template-apache-frontend]
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-apache-frontend.cfg url = ${:_profile_base_location_}/instance-apache-frontend.cfg
md5sum = 9f3eec91f43ae0730e9bba93f83572fc md5sum = f0a507fed2b1dcab5530c892adce8327
output = ${buildout:directory}/template-apache-frontend.cfg output = ${buildout:directory}/template-apache-frontend.cfg
mode = 0644 mode = 0644
...@@ -71,7 +72,7 @@ mode = 0644 ...@@ -71,7 +72,7 @@ mode = 0644
[template-slave-list] [template-slave-list]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/apache-custom-slave-list.cfg.in url = ${:_profile_base_location_}/templates/apache-custom-slave-list.cfg.in
md5sum = f5eef006211809669b12422240c6f436 md5sum = f002a8fc8fc5d18adbd8ac1ee054e852
mode = 640 mode = 640
[template-slave-configuration] [template-slave-configuration]
...@@ -83,13 +84,13 @@ mode = 640 ...@@ -83,13 +84,13 @@ mode = 640
[template-replicate-publish-slave-information] [template-replicate-publish-slave-information]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/replicate-publish-slave-information.cfg.in url = ${:_profile_base_location_}/templates/replicate-publish-slave-information.cfg.in
md5sum = 61a14dff06718e3d90c346a0a7b20c5a md5sum = a2cf00b24877bf747e2408d444f16f05
mode = 640 mode = 640
[template-apache-frontend-configuration] [template-apache-frontend-configuration]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/apache.conf.in url = ${:_profile_base_location_}/templates/apache.conf.in
md5sum = b4d7461c29fb6c36f09e48fa5ad59fba md5sum = bae89ebc6c5e75b12535fbd6c37f647d
mode = 640 mode = 640
[template-apache-cached-configuration] [template-apache-cached-configuration]
...@@ -129,6 +130,12 @@ url = ${:_profile_base_location_}/templates/default-virtualhost.conf.in ...@@ -129,6 +130,12 @@ url = ${:_profile_base_location_}/templates/default-virtualhost.conf.in
md5sum = ac845c0fa3835832307a0e7323cb339d md5sum = ac845c0fa3835832307a0e7323cb339d
mode = 640 mode = 640
[template-log-access]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/template-log-access.conf.in
md5sum = f85005b430978f3bd24ee7ce11b0e304
mode = 640
[template-squid-configuration] [template-squid-configuration]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/squid.conf.jinja2 url = ${:_profile_base_location_}/templates/squid.conf.jinja2
......
...@@ -27,6 +27,7 @@ parts = ...@@ -27,6 +27,7 @@ parts =
promise-apache-frontend-v6-http promise-apache-frontend-v6-http
promise-apache-cached promise-apache-cached
eggs-directory = ${buildout:eggs-directory} eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory} develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true offline = true
...@@ -87,6 +88,13 @@ configuration.apache-certificate = ...@@ -87,6 +88,13 @@ configuration.apache-certificate =
configuration.open-port = 80 443 configuration.open-port = 80 443
configuration.extra_slave_instance_list = configuration.extra_slave_instance_list =
[frontend-configuration]
template-log-access = ${template-log-access:target}
log-access-configuration = $${directory:etc}/apache-log-access.conf
apache-directory = ${apache-2.2:location}
apache-ipv6 = $${instance-parameter:ipv6-random}
apache-https-port = $${instance-parameter:configuration.port}
[jinja2-template-base] [jinja2-template-base]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
rendered = $${buildout:directory}/$${:filename} rendered = $${buildout:directory}/$${:filename}
...@@ -129,6 +137,9 @@ extra-context = ...@@ -129,6 +137,9 @@ extra-context =
raw template_slave_configuration ${template-slave-configuration:target} raw template_slave_configuration ${template-slave-configuration:target}
raw template_rewrite_cached ${template-rewrite-cached:target} raw template_rewrite_cached ${template-rewrite-cached:target}
raw software_type single-custom-personal raw software_type single-custom-personal
section logrotate_dict logrotate
section frontend_configuration frontend-configuration
section apache_configuration apache-configuration
[dynamic-custom-group-template-slave-list] [dynamic-custom-group-template-slave-list]
< = jinja2-template-base < = jinja2-template-base
...@@ -214,6 +225,7 @@ extra-context = ...@@ -214,6 +225,7 @@ extra-context =
key error_log apache-configuration:error-log key error_log apache-configuration:error-log
key pid_file apache-configuration:pid-file key pid_file apache-configuration:pid-file
key slave_configuration_directory apache-directory:slave-configuration key slave_configuration_directory apache-directory:slave-configuration
section frontend_configuration frontend-configuration
[apache-frontend] [apache-frontend]
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
...@@ -366,7 +378,7 @@ state-file = $${directory:srv}/logrotate.status ...@@ -366,7 +378,7 @@ state-file = $${directory:srv}/logrotate.status
<= logrotate <= logrotate
recipe = slapos.cookbook:logrotate.d recipe = slapos.cookbook:logrotate.d
name = apache name = apache
log = $${apache-directory:slave-log}/*_log $${apache-configuration:error-log} $${apache-configuration:access-log} log = $${apache-configuration:error-log} $${apache-configuration:access-log}
frequency = daily frequency = daily
rotatep-num = 30 rotatep-num = 30
post = ${buildout:bin-directory}/killpidfromfile $${apache-configuration:pid-file} SIGUSR1 post = ${buildout:bin-directory}/killpidfromfile $${apache-configuration:pid-file} SIGUSR1
...@@ -425,7 +437,7 @@ pid-filename-path = $${directory:run}/squid.pid ...@@ -425,7 +437,7 @@ pid-filename-path = $${directory:run}/squid.pid
template = ${template-squid-configuration:target} template = ${template-squid-configuration:target}
rendered = $${squid-cache:configuration-path} rendered = $${squid-cache:configuration-path}
extra-context = extra-context =
key ip squid-cache:ip key ip squid-cache:ip
key port squid-cache:port key port squid-cache:port
key backend_ip squid-cache:backend-ip key backend_ip squid-cache:backend-ip
key backend_port squid-cache:backend-port key backend_port squid-cache:backend-port
......
...@@ -13,7 +13,7 @@ meld3 = 0.6.10 ...@@ -13,7 +13,7 @@ meld3 = 0.6.10
pycrypto = 2.6 pycrypto = 2.6
rdiff-backup = 1.0.5 rdiff-backup = 1.0.5
slapos.recipe.build = 0.11.6 slapos.recipe.build = 0.11.6
slapos.recipe.cmmi = 0.1 slapos.recipe.cmmi = 0.1.1
slapos.recipe.template = 2.4.2 slapos.recipe.template = 2.4.2
slapos.toolbox = 0.34.0 slapos.toolbox = 0.34.0
smmap = 0.8.2 smmap = 0.8.2
...@@ -23,7 +23,15 @@ cmd2 = 0.6.5.1 ...@@ -23,7 +23,15 @@ cmd2 = 0.6.5.1
prettytable = 0.7.2 prettytable = 0.7.2
requests = 1.2.3 requests = 1.2.3
slapos.cookbook = 0.82 slapos.cookbook = 0.82
cffi = 0.8.2
cryptography = 0.3
plone.recipe.command = 1.1
pyOpenSSL = 0.14
six = 1.6.1
# Required by:
# cffi==0.8.2
pycparser = 2.10
# Required by: # Required by:
# slapos.cookbook==0.82 # slapos.cookbook==0.82
lock-file = 2.0 lock-file = 2.0
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
{% set part_list = [] -%} {% set part_list = [] -%}
{% set cache_access = "http://%s:%s" % (local_ipv4, cache_port) -%} {% set cache_access = "http://%s:%s" % (local_ipv4, cache_port) -%}
{% set generic_instance_parameter_dict = {'cache_access': cache_access,} -%} {% set generic_instance_parameter_dict = {'cache_access': cache_access,} -%}
{% set slave_log_dict = {} -%}
{% if extra_slave_instance_list -%} {% if extra_slave_instance_list -%}
{% set slave_instance_information_list = []-%} {% set slave_instance_information_list = [] -%}
{% set slave_instance_list = slave_instance_list + json_module.loads(extra_slave_instance_list) -%} {% set slave_instance_list = slave_instance_list + json_module.loads(extra_slave_instance_list) -%}
{% endif -%} {% endif -%}
[jinja2-template-base] [jinja2-template-base]
...@@ -17,15 +18,73 @@ context = ...@@ -17,15 +18,73 @@ context =
key develop_eggs_directory buildout:develop-eggs-directory key develop_eggs_directory buildout:develop-eggs-directory
${:extra-context} ${:extra-context}
{% do logrotate_dict.pop('recipe') %}
[logrotate]
{% for key, value in logrotate_dict.iteritems() -%}
{{ key }} = {{ value }}
{% endfor %}
# Loop trhought slave list to set up slaves # Loop trhought slave list to set up slaves
{% for slave_instance in slave_instance_list -%} {% for slave_instance in slave_instance_list -%}
{% set slave_reference = slave_instance.get('slave_reference') -%} {% set slave_reference = slave_instance.get('slave_reference') -%}
{% set slave_section_title = 'dynamic-template-slave-instance-%s' % slave_reference -%} {% set slave_section_title = 'dynamic-template-slave-instance-%s' % slave_reference -%}
{% set slave_parameter_dict = generic_instance_parameter_dict.copy() -%} {% set slave_parameter_dict = generic_instance_parameter_dict.copy() -%}
{% do part_list.append(slave_section_title) -%} {% do part_list.append(slave_section_title) -%}
{% set slave_directory_section = slave_reference + "-directory" -%}
{% set slave_log_folder = logrotate_dict.get('backup') + '/' + slave_reference + "-logs" -%}
[{{slave_directory_section}}]
recipe = slapos.cookbook:mkdirectory
log-folder = {{slave_log_folder}}
# Set Up log files # Set Up log files
{% do slave_parameter_dict.__setitem__('access_log', '/'.join([apache_log_directory, '%s_access_log' % slave_reference])) -%} {% do slave_parameter_dict.__setitem__('access_log', '/'.join([apache_log_directory, '%s_access_log' % slave_reference])) -%}
{% do slave_parameter_dict.__setitem__('error_log', '/'.join([apache_log_directory, '%s_error_log' % slave_reference])) -%} {% do slave_parameter_dict.__setitem__('error_log', '/'.join([apache_log_directory, '%s_error_log' % slave_reference])) -%}
# Set slave logrotate entry
{% set slave_logrotate_section = slave_reference + "-logs" -%}
{% do part_list.append(slave_logrotate_section) -%}
[{{slave_logrotate_section}}]
<= logrotate
recipe = slapos.cookbook:logrotate.d
name = ${:_buildout_section_name_}
log = {{slave_parameter_dict.get('access_log')}} {{slave_parameter_dict.get('error_log')}}
backup = {{ '${' + slave_directory_section + ':log-folder}' }}
frequency = daily
rotatep-num = 30
post = ${buildout:bin-directory}/killpidfromfile {{ apache_configuration.get('pid-file') }} SIGUSR1
sharedscripts = true
notifempty = true
create = true
# integrate current logs inside
{% set slave_ln_section = slave_reference + "-ln" -%}
{% do part_list.append(slave_ln_section) -%}
[{{slave_ln_section}}]
recipe = plone.recipe.command
stop-on-error = false
command = ln -s {{slave_parameter_dict.get('error_log')}} {{ '${' + slave_directory_section + ':log-folder}' }}/apache-error.log && ln -s {{slave_parameter_dict.get('access_log')}} {{ '${' + slave_directory_section + ':log-folder}' }}/apache-access.log
# Set password for slave
{% set slave_password_section = slave_reference + "-password" -%}
[{{slave_password_section}}]
recipe = slapos.cookbook:generate.password
storage-path = {{apache_configuration_directory}}/.{{slave_reference}}.passwd
bytes = 8
# Set up htaccess file for slave
{% set slave_htaccess_section = slave_reference + '-htaccess' %}
{% do part_list.append(slave_htaccess_section) -%}
[{{slave_htaccess_section}}]
recipe = plone.recipe.command
stop-on-error = true
htaccess-path = {{apache_configuration_directory}}/.{{slave_reference}}.htaccess
command = {{frontend_configuration.get('apache-directory')}}/bin/htpasswd -cb ${:htaccess-path} {{ slave_reference }} {{ '${' + slave_password_section + ':passwd}' }}
# Add slave log directory to the slave log access dict
{% do slave_log_dict.__setitem__(slave_reference, slave_log_folder) %}
# Set up apache configuration file for slave # Set up apache configuration file for slave
[{{ slave_section_title }}] [{{ slave_section_title }}]
< = jinja2-template-base < = jinja2-template-base
...@@ -72,18 +131,37 @@ apache_custom_https = {{ dumps(apache_custom_https) }} ...@@ -72,18 +131,37 @@ apache_custom_https = {{ dumps(apache_custom_https) }}
{% endif -%} {% endif -%}
# Publish slave information # Publish slave information
{% set slave_log_access_url = 'https://' + slave_reference + ':${'+ slave_password_section +':passwd}@[' + frontend_configuration.get('apache-ipv6') + ']:' + frontend_configuration.get('apache-https-port') + '/' + slave_reference.lower() + '/' %}
{% if not extra_slave_instance_list -%} {% if not extra_slave_instance_list -%}
{% set publish_section_title = 'publish-%s-connection-information' % slave_instance.get('slave_reference') -%} {% set publish_section_title = 'publish-%s-connection-information' % slave_instance.get('slave_reference') -%}
{% do part_list.append(publish_section_title) -%} {% do part_list.append(publish_section_title) -%}
[{{ publish_section_title }}] [{{ publish_section_title }}]
recipe = slapos.cookbook:publish recipe = slapos.cookbook:publish
public-ipv4 = {{ public_ipv4 }} public-ipv4 = {{ public_ipv4 }}
log-access = {{ slave_log_access_url }}
-slave-reference = {{ slave_instance.get('slave_reference') }} -slave-reference = {{ slave_instance.get('slave_reference') }}
{% else -%} {% else -%}
{% do slave_instance_information_list.append({'slave-reference':slave_instance.get('slave_reference'), 'public-ipv4':public_ipv4}) -%} {% do slave_instance_information_list.append({'slave-reference':slave_instance.get('slave_reference'), 'public-ipv4':public_ipv4, 'log-access': slave_log_access_url}) -%}
{% endif -%} {% endif -%}
{% endfor -%} {% endfor -%}
[slave-log-directories]
{% for key, value in slave_log_dict.iteritems() -%}
{{ key }} = {{ value }}
{% endfor %}
# Define log access
{% set log_access_section = "apache-log-access" %}
{% do part_list.append(log_access_section) -%}
[{{log_access_section}}]
< = jinja2-template-base
template = {{frontend_configuration.get('template-log-access')}}
rendered = {{frontend_configuration.get('log-access-configuration')}}
extra-context =
section slave_log_directory slave-log-directories
raw apache_log_directory {{apache_log_directory}}
raw apache_configuration_directory {{apache_configuration_directory}}
# Publish information for the instance # Publish information for the instance
{% set publish_section_title = 'publish-apache-information' -%} {% set publish_section_title = 'publish-apache-information' -%}
{% do part_list.append(publish_section_title) -%} {% do part_list.append(publish_section_title) -%}
......
...@@ -64,6 +64,11 @@ LoadModule headers_module {{ httpd_home }}/modules/mod_headers.so ...@@ -64,6 +64,11 @@ LoadModule headers_module {{ httpd_home }}/modules/mod_headers.so
LoadModule cache_module {{ httpd_home }}/modules/mod_cache.so LoadModule cache_module {{ httpd_home }}/modules/mod_cache.so
LoadModule mem_cache_module {{ httpd_home }}/modules/mod_mem_cache.so LoadModule mem_cache_module {{ httpd_home }}/modules/mod_mem_cache.so
LoadModule antiloris_module {{ httpd_home }}/modules/mod_antiloris.so LoadModule antiloris_module {{ httpd_home }}/modules/mod_antiloris.so
LoadModule alias_module {{ httpd_home }}/modules/mod_alias.so
LoadModule autoindex_module {{ httpd_home }}/modules/mod_autoindex.so
LoadModule auth_basic_module {{ httpd_home }}/modules/mod_auth_basic.so
LoadModule authz_user_module {{ httpd_home }}/modules/mod_authz_user.so
LoadModule authn_file_module {{ httpd_home }}/modules/mod_authn_file.so
# The following directives modify normal HTTP response behavior to # The following directives modify normal HTTP response behavior to
# handle known problems with browser implementations. # handle known problems with browser implementations.
...@@ -125,6 +130,8 @@ SSLCipherSuite RC4-SHA:HIGH:!ADH ...@@ -125,6 +130,8 @@ SSLCipherSuite RC4-SHA:HIGH:!ADH
SSLProxyCheckPeerCN off SSLProxyCheckPeerCN off
SSLProxyCheckPeerExpire off SSLProxyCheckPeerExpire off
include {{frontend_configuration.get('log-access-configuration')}}
NameVirtualHost *:{{ http_port }} NameVirtualHost *:{{ http_port }}
NameVirtualHost *:{{ https_port }} NameVirtualHost *:{{ https_port }}
include {{ slave_configuration_directory }}/*.conf include {{ slave_configuration_directory }}/*.conf
\ No newline at end of file
...@@ -6,8 +6,15 @@ ...@@ -6,8 +6,15 @@
{% set slave_list = json_module.loads(slave_list_raw) -%} {% set slave_list = json_module.loads(slave_list_raw) -%}
{% for slave_dict in slave_list -%} {% for slave_dict in slave_list -%}
{% set slave_reference = slave_dict.pop('slave-reference') %} {% set slave_reference = slave_dict.pop('slave-reference') %}
{% set log_access_url = slave_dict.pop('log-access', '') %}
{% set current_slave_dict = slave_information_dict.get(slave_reference, {}) %} {% set current_slave_dict = slave_information_dict.get(slave_reference, {}) %}
{% do current_slave_dict.update(slave_dict) -%} {% do current_slave_dict.update(slave_dict) -%}
{% set log_access_list = current_slave_dict.get('log-access-urls', []) %}
{% do log_access_list.append( frontend + ': ' + log_access_url) %}
{% do current_slave_dict.__setitem__(
'log-access-urls',
log_access_list
) %}
{% do current_slave_dict.__setitem__( {% do current_slave_dict.__setitem__(
'replication_number', 'replication_number',
current_slave_dict.get('replication_number', 0) + 1 current_slave_dict.get('replication_number', 0) + 1
...@@ -23,6 +30,7 @@ ...@@ -23,6 +30,7 @@
[{{ publish_section_title }}] [{{ publish_section_title }}]
recipe = slapos.cookbook:publish recipe = slapos.cookbook:publish
-slave-reference = {{ slave_reference }} -slave-reference = {{ slave_reference }}
log-access-url = {{ json_module.dumps(slave_information.pop('log-access-urls', 1000)) }}
{% for key, value in slave_information.iteritems() -%} {% for key, value in slave_information.iteritems() -%}
{{ key }} = {{ value }} {{ key }} = {{ value }}
{% endfor -%} {% endfor -%}
......
{% for slave, directory in slave_log_directory.iteritems() %}
Alias /{{slave}}/ {{directory}}/
<Directory {{directory}}>
Order Deny,Allow
Deny from env=AUTHREQUIRED
<Files ".??*">
Order Allow,Deny
Deny from all
</Files>
AuthType Basic
AuthName "Log Access {{slave}}"
AuthUserFile "{{ apache_configuration_directory + '/.' + slave.upper() + '.htaccess'}}"
Require user {{slave.upper()}}
Options Indexes FollowSymLinks
Satisfy all
</Directory>
{% endfor %}
...@@ -4,7 +4,6 @@ extends = ...@@ -4,7 +4,6 @@ extends =
../../stack/slapos.cfg ../../stack/slapos.cfg
../../component/git/buildout.cfg ../../component/git/buildout.cfg
../../component/phantomjs/buildout.cfg ../../component/phantomjs/buildout.cfg
../../component/git/buildout.cfg
../../component/python-2.7/buildout.cfg ../../component/python-2.7/buildout.cfg
../../component/python-setuptools/buildout.cfg ../../component/python-setuptools/buildout.cfg
......
...@@ -21,9 +21,6 @@ develop = ...@@ -21,9 +21,6 @@ develop =
${:parts-directory}/slapos.cookbook-repository ${:parts-directory}/slapos.cookbook-repository
extensions = buildout-versions
[slapos.cookbook-repository] [slapos.cookbook-repository]
recipe = slapos.recipe.build:gitclone recipe = slapos.recipe.build:gitclone
repository = http://git.erp5.org/repos/slapos.git repository = http://git.erp5.org/repos/slapos.git
......
[buildout] [buildout]
extensions = buildout-versions
extends = extends =
../../component/xorg/buildout.cfg ../../component/xorg/buildout.cfg
../../component/lxml-python/buildout.cfg ../../component/lxml-python/buildout.cfg
...@@ -52,86 +50,30 @@ mode = 0644 ...@@ -52,86 +50,30 @@ mode = 0644
# pin version of setuptools # pin version of setuptools
setuptools = 2.2 setuptools = 2.2
Flask = 0.10.1
Jinja2 = 2.7.2 Jinja2 = 2.7.2
MarkupSafe = 0.19 MarkupSafe = 0.19
Werkzeug = 0.9.4 Werkzeug = 0.9.4
buildout-versions = 1.7 buildout-versions = 1.7
cffi = 0.8.2 cliff = 1.6.0
cmd2 = 0.6.7 cmd2 = 0.6.7
cryptography = 0.2.2
itsdangerous = 0.23
meld3 = 0.6.10
pyOpenSSL = 0.14
pyparsing = 2.0.1
slapos.cookbook = 0.85
slapos.recipe.build = 0.12
slapos.recipe.cmmi = 0.2
slapos.recipe.template = 2.5
# Required by:
# slapos.core==1.0.3
Flask = 0.10.1
# Required by:
# slapos.core==1.0.3
cliff = 1.5.2
# Required by:
# slapos.cookbook==0.85
inotifyx = 0.2.0-1 inotifyx = 0.2.0-1
itsdangerous = 0.24
# Required by:
# slapos.cookbook==0.85
lock-file = 2.0 lock-file = 2.0
lxml = 3.3.4
# Required by: meld3 = 0.6.10
# slapos.cookbook==0.85
# slapos.core==1.0.3
# xml-marshaller==0.9.7
lxml = 3.3.3
# Required by:
# slapos.cookbook==0.85
netaddr = 0.7.11 netaddr = 0.7.11
# Required by:
# slapos.core==1.0.3
netifaces = 0.8-1 netifaces = 0.8-1
pyparsing = 2.0.1
# Required by: pytz = 2014.2
# cffi==0.8.2
pycparser = 2.10
# Required by:
# slapos.cookbook==0.85
pytz = 2014.1
# Required by:
# slapos.core==1.0.3
requests = 2.2.1 requests = 2.2.1
# Required by:
# cliff==1.5.2
six = 1.6.1 six = 1.6.1
slapos.cookbook = 0.85
# Required by:
# slapos.cookbook==0.85
slapos.core = 1.0.3 slapos.core = 1.0.3
slapos.recipe.cmmi = 0.2
# Required by: stevedore = 0.15
# cliff==1.5.2
stevedore = 0.14.1
# Required by:
# slapos.core==1.0.3
supervisor = 3.0 supervisor = 3.0
# Required by:
# slapos.cookbook==0.85
xml-marshaller = 0.9.7 xml-marshaller = 0.9.7
# Required by:
# slapos.core==1.0.3
zope.interface = 4.1.1 zope.interface = 4.1.1
[networkcache] [networkcache]
......
...@@ -3,10 +3,6 @@ ...@@ -3,10 +3,6 @@
develop = develop =
${:parts-directory}/slapos.cookbook-repository ${:parts-directory}/slapos.cookbook-repository
extensions =
slapos.zcbworkarounds
mr.developer
find-links = find-links =
http://www.nexedi.org/static/packages/source/slapos.buildout/ http://www.nexedi.org/static/packages/source/slapos.buildout/
http://www.nexedi.org/static/packages/source/hexagonit.recipe.download/ http://www.nexedi.org/static/packages/source/hexagonit.recipe.download/
......
[buildout] [buildout]
extensions =
slapos.zcbworkarounds
buildout-versions
mr.developer
find-links = find-links =
http://www.nexedi.org/static/packages/source/slapos.buildout/ http://www.nexedi.org/static/packages/source/slapos.buildout/
http://www.nexedi.org/static/packages/source/hexagonit.recipe.download/ http://www.nexedi.org/static/packages/source/hexagonit.recipe.download/
...@@ -97,5 +92,17 @@ develop += ...@@ -97,5 +92,17 @@ develop +=
${:parts-directory}/cloudooo ${:parts-directory}/cloudooo
[versions] [versions]
# Use SlapOS patched zc.buildout Paste = 1.7.5.1
zc.buildout = 1.6.0-dev-SlapOS-006 PasteDeploy = 1.5.2
PasteScript = 1.7.5
WSGIUtils = 0.7
argparse = 1.1
buildout-versions = 1.7
erp5.util = 0.4.37
lxml = 3.3.4
plone.recipe.command = 1.1
psutil = 2.0.0
python-magic = 0.4.6
slapos.recipe.build = 0.12
slapos.recipe.cmmi = 0.2
zope.interface = 4.1.1
...@@ -4,10 +4,6 @@ develop = ...@@ -4,10 +4,6 @@ develop =
${:parts-directory}/slapos.cookbook-repository ${:parts-directory}/slapos.cookbook-repository
${:parts-directory}/cloudooo-repository ${:parts-directory}/cloudooo-repository
extensions =
slapos.zcbworkarounds
mr.developer
find-links = find-links =
http://www.nexedi.org/static/packages/source/slapos.buildout/ http://www.nexedi.org/static/packages/source/slapos.buildout/
http://www.nexedi.org/static/packages/source/hexagonit.recipe.download/ http://www.nexedi.org/static/packages/source/hexagonit.recipe.download/
......
...@@ -13,6 +13,8 @@ download-cache = ...@@ -13,6 +13,8 @@ download-cache =
# Generate list of automatically chosen eggs version # Generate list of automatically chosen eggs version
extensions += extensions +=
buildout-versions buildout-versions
buildout.dumppickedversions
mr.developer
# Use shacache and lxml # Use shacache and lxml
extends = extends =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment