[DRBD-cvs] svn commit by phil - r2059 - in trunk: . scripts user - Worked on item 28 of the ROADMAP. 50% done.

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Sun Feb 5 21:51:51 CET 2006


Author: phil
Date: 2006-02-05 21:51:49 +0100 (Sun, 05 Feb 2006)
New Revision: 2059

Added:
   trunk/user/drbdadm_usage_cnt.c
Modified:
   trunk/ROADMAP
   trunk/scripts/drbd.conf
   trunk/user/Makefile
   trunk/user/drbd_endian.h
   trunk/user/drbdadm.h
   trunk/user/drbdadm_main.c
   trunk/user/drbdadm_parser.c
   trunk/user/drbdadm_parser.h
   trunk/user/drbdadm_scanner.fl
Log:
Worked on item 28 of the ROADMAP. 50% done.


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/ROADMAP	2006-02-05 20:51:49 UTC (rev 2059)
@@ -667,6 +667,9 @@
    set gets generated, the 'call home' is initiated. The user might
    of course opt out of this.
 
+   50% DONE [ Counting of resources is missing, counting of DRBD releases
+              is alrady implemented. ]
+
 29 Make drbdadm to have 'hidden-commands' command to also show
    the hidden sub-commands in the ussage.
 

Modified: trunk/scripts/drbd.conf
===================================================================
--- trunk/scripts/drbd.conf	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/scripts/drbd.conf	2006-02-05 20:51:49 UTC (rev 2059)
@@ -84,6 +84,11 @@
 
     # You might disable one of drbdadm's sanity check.
     # disable-ip-verification;
+
+    # Participate in DRBD's online usage counter at http://usage.drbd.org
+    # possilbe options: ask, yes, no. Default is ask. In case you do not
+    # know, leave it at ask, and follow the on screen instructions later.
+    # usage-count ask;
 # }
 
 

Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/Makefile	2006-02-05 20:51:49 UTC (rev 2059)
@@ -21,7 +21,8 @@
 CC = gcc
 
 drbdadm-obj = drbdadm_scanner.o drbdadm_parser.o drbdadm_main.o \
-	      drbdadm_adjust.o drbdtool_common.o ../drbd/drbd_buildtag.o
+	      drbdadm_adjust.o drbdtool_common.o drbdadm_usage_cnt.o \
+	      ../drbd/drbd_buildtag.o
 
 drbdsetup-obj = drbdsetup.o drbdtool_common.o ../drbd/drbd_buildtag.o \
 	        ../drbd/drbd_strings.o
@@ -73,3 +74,4 @@
 drbdsetup.o:       drbdtool_common.h           drbd_limits.h
 drbdsetup.o: ../drbd/linux/drbd.h ../drbd/linux/drbd_config.h
 drbdmeta.o:        drbdtool_common.h drbd_endian.h 
+drbdadm_usage_cnt.o: drbdadm.h drbd_endian.h

Modified: trunk/user/drbd_endian.h
===================================================================
--- trunk/user/drbd_endian.h	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/drbd_endian.h	2006-02-05 20:51:49 UTC (rev 2059)
@@ -166,12 +166,12 @@
  */
 
 #if BITS_PER_LONG == 32
-# define X32 "%lX"
+# define X32 "%X"
 //# define X64 "%llX"
 # define X64(a) "%"#a"llX"
-# define D32 "%ld"
+# define D32 "%d"
 # define D64 "%lld"
-# define U32 "%lu"
+# define U32 "%u"
 # define U64 "%llu"
 #elif BITS_PER_LONG == 64
 # define X32 "%X"

Modified: trunk/user/drbdadm.h
===================================================================
--- trunk/user/drbdadm.h	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/drbdadm.h	2006-02-05 20:51:49 UTC (rev 2059)
@@ -33,13 +33,19 @@
 /* for verify_ips(): are not verifyable ips fatal? */
 #define INVALID_IP_IS_INVALID_CONF 0
 
-
+enum usage_count_type {
+  UC_YES,
+  UC_NO,
+  UC_ASK,
+};
+  
 struct d_globals
 {
   int disable_io_hints;
   int disable_ip_verification;
   int minor_count;
   int dialog_refresh;
+  enum usage_count_type usage_count;
 };
 
 struct d_host_info
@@ -87,8 +93,8 @@
 extern void schedule_dcmd( int (* function)(struct d_resource*,const char* ),
 			   struct d_resource* res,
 			   int order);
+extern void uc_node(enum usage_count_type type);
 
-
 extern char* config_file;
 extern int config_valid;
 extern struct d_resource* config;

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/drbdadm_main.c	2006-02-05 20:51:49 UTC (rev 2059)
@@ -106,7 +106,7 @@
 struct utsname nodeinfo;
 int line=1;
 int fline, c_resource_start;
-struct d_globals global_options = { 0, 0, 0, 1 };
+struct d_globals global_options = { 0, 0, 0, 1, UC_ASK };
 char *config_file = NULL;
 struct d_resource* config = NULL;
 struct d_resource* common = NULL;
@@ -1530,6 +1530,8 @@
     find_drbdcmd(&drbdmeta,(char *[]){"./drbdmeta", "/sbin/drbdmeta", 0 });
   }
 
+  uc_node(global_options.usage_count);
+
   if(cmd->res_name_required)
     {
       int is_dump = (cmd->function == adm_dump);

Modified: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/drbdadm_parser.c	2006-02-05 20:51:49 UTC (rev 2059)
@@ -205,6 +205,7 @@
 	token = yylex(); 				\
 	if(token != TOKEN1)				\
 		pe_expected_got( #TOKEN1, token ); 	\
+	token;						\
 })
 
 #define EXP2(TOKEN1,TOKEN2)					\
@@ -213,6 +214,7 @@
 	token = yylex(); 					\
 	if(token != TOKEN1 && token != TOKEN2) 			\
 		pe_expected_got( #TOKEN1 "|" # TOKEN2, token );	\
+	token;							\
 })
 
 static void pe_expected(const char *exp)
@@ -245,6 +247,14 @@
 			range_check(R_DIALOG_REFRESH,"dialog-refresh",yylval.txt);
 			global_options.dialog_refresh=atoi(yylval.txt);
 			break;
+		case TK_USAGE_COUNT:
+			switch(yylex()) {
+			case TK_YES: global_options.usage_count=UC_YES; break; 
+			case TK_NO:  global_options.usage_count=UC_NO;  break; 
+			case TK_ASK: global_options.usage_count=UC_ASK; break; 
+			default:     pe_expected("yes | no | ask");
+			}
+			break;
 		case '}':
 			return;
 		default:

Modified: trunk/user/drbdadm_parser.h
===================================================================
--- trunk/user/drbdadm_parser.h	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/drbdadm_parser.h	2006-02-05 20:51:49 UTC (rev 2059)
@@ -79,7 +79,11 @@
 	TK_SYNCER_OPTION,
 	TK_STARTUP_SWITCH,
 	TK_STARTUP_OPTION,
-	TK_HANDLER_OPTION
+	TK_HANDLER_OPTION,
+	TK_USAGE_COUNT,
+	TK_ASK,
+	TK_YES,
+	TK_NO
 };
 
 typedef struct YYSTYPE {

Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/drbdadm_scanner.fl	2006-02-05 20:51:49 UTC (rev 2059)
@@ -44,7 +44,10 @@
 {WS}			/* ignore whitespaces */
 {OPCHAR}		{ DP; return yytext[0];			}
 on			{ DP; return TK_ON;			}
+no			{ DP; return TK_NO;			}
 net			{ DP; return TK_NET;			}
+yes			{ DP; return TK_YES;			}
+ask			{ DP; return TK_ASK;			}
 skip			{ DP; return TK_SKIP;			}
 disk			{ DP; return TK_DISK;			}
 syncer			{ DP; return TK_SYNCER;			}
@@ -62,6 +65,7 @@
 resource		{ DP; return TK_RESOURCE;		}
 meta-disk		{ DP; return TK_META_DISK;		}
 flexible-meta-disk	{ DP; return TK_FLEX_META_DISK;		}
+usage-count 		{ DP; return TK_USAGE_COUNT;		}
 size			{ DP; CP; RC(DISK_SIZE); return TK_DISK_OPTION;	}
 on-io-error		{ DP; CP; return TK_DISK_OPTION;	}
 split-brain-fix		{ DP; CP; return TK_DISK_SWITCH;	}

Added: trunk/user/drbdadm_usage_cnt.c
===================================================================
--- trunk/user/drbdadm_usage_cnt.c	2006-02-02 17:43:39 UTC (rev 2058)
+++ trunk/user/drbdadm_usage_cnt.c	2006-02-05 20:51:49 UTC (rev 2059)
@@ -0,0 +1,315 @@
+/*
+   drbdadm_usage_cnt.c
+
+   This file is part of drbd by Philipp Reisner.
+
+   Copyright (C) 2006, Philipp Reisner <philipp.reisner at linbit.com>.
+        Initial author.
+
+   Copyright (C) 2006, Lars Ellenberg <l.g.e at web.de>
+        contributions.
+
+   drbd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   drbd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with drbd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "drbdadm.h"
+#include "drbd_endian.h"
+#include "linux/drbd.h"		/* only use DRBD_MAGIC from here! */
+
+#define HTTP_PORT 80
+#define HTTP_HOST "usage.drbd.org"
+#define HTTP_ADDR "212.69.162.23"
+#define NODE_ID_FILE "/var/lib/drbd/node_id"
+
+struct node_info {
+	u64	node_uuid;
+	u32	version_code;
+};
+
+struct node_info_od {
+	u32 magic;
+	struct node_info ni;
+} __attribute((packed));
+
+/* FIX: mark plus versions, mark production vs beta releases.
+        read the version string from the /proc file, so we
+	look at the version of the module and not at the version
+	of the drbdadm executable.
+ */
+static unsigned int numeric_version_code(char* text)
+{
+	unsigned int nc;
+	char buffer[5], *c, *b;
+	unsigned m = 1000000;
+
+	nc = 0;
+	c = text;
+
+	while(*c) {
+		while(!isdigit(*c)) c++;
+		b = buffer;
+		while(isdigit(*c)) *b++=*c++;
+		*b=0;
+
+		nc = nc + atoi( buffer ) * m;
+		m=m/1000;
+	}
+
+	return nc;
+}
+
+static void get_random_bytes(void* buffer, int len)
+{
+	int fd;
+
+	fd = open("/dev/random",O_RDONLY);
+	if( fd == -1) {
+		perror("Open of /dev/random failed");
+		exit(20);
+	}
+	if(read(fd,buffer,len) != len) {
+		fprintf(stderr,"Reading from /dev/random failed\n");
+		exit(20);
+	}
+	close(fd);	
+}
+
+static void write_node_id(struct node_info *ni)
+{
+	int fd;
+	struct node_info_od on_disk;
+
+	fd = open(NODE_ID_FILE,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
+	if( fd == -1) {
+		perror("Creation of "NODE_ID_FILE" failed.");
+		exit(20);
+	}
+
+	on_disk.magic           = cpu_to_be32(DRBD_MAGIC);
+	on_disk.ni.node_uuid    = cpu_to_be64(ni->node_uuid);
+	on_disk.ni.version_code = cpu_to_be32(ni->version_code);
+
+	if( write(fd,&on_disk, sizeof(on_disk)) != sizeof(on_disk)) {
+		perror("Write to "NODE_ID_FILE" failed.");
+		exit(20);
+	}
+
+	close(fd);
+}
+
+
+static int read_node_id(struct node_info *ni)
+{
+	int fd;
+	struct node_info_od on_disk;
+
+	fd = open(NODE_ID_FILE,O_RDONLY);
+	if( fd == -1) {
+		return 0;
+	}
+	
+	if( read(fd,&on_disk, sizeof(on_disk)) != sizeof(on_disk)) {
+		close(fd);
+		return 0;
+	}
+
+	if ( be32_to_cpu(on_disk.magic) != DRBD_MAGIC ) return 0;
+
+	ni->node_uuid    = be64_to_cpu(on_disk.ni.node_uuid);
+	ni->version_code = be32_to_cpu(on_disk.ni.version_code);
+
+	close(fd);
+	return 1;
+}
+
+/**
+ * insert_usage_with_socket:
+ * 
+ * Return codes:
+ *
+ * 0 - success
+ * 1 - failed to create socket
+ * 2 - unknown server
+ * 3 - cannot connect to server
+ * 5 - other error
+ */
+static int make_get_request(char *req_buf) {
+	struct sockaddr_in server;
+	struct hostent *host_info;
+	unsigned long addr;
+	int sock;
+	char *http_host = HTTP_HOST;
+	int buf_len = 1024;
+	char buffer[buf_len];
+	FILE *sockfd;
+	int writeit;
+	sock = socket( PF_INET, SOCK_STREAM, 0);
+	if (sock < 0) {
+		return 1;
+	}
+	memset (&server, 0, sizeof(server));
+
+	/* convert host name to ip */
+	host_info = gethostbyname(http_host);
+	if (host_info == NULL) {
+		/* unknown host, try with ip */
+		if ((addr = inet_addr( HTTP_ADDR )) != INADDR_NONE)
+			memcpy((char *)&server.sin_addr, &addr, sizeof(addr));
+		else {
+			close(sock);
+			return 2;
+		}
+	} else {
+		memcpy((char *)&server.sin_addr, host_info->h_addr,
+			host_info->h_length);
+	}
+
+	server.sin_family = AF_INET;
+	server.sin_port = htons(HTTP_PORT);
+
+	if (connect(sock, (struct sockaddr*)&server, sizeof(server))<0) {
+		/* cannot connect to server */
+		close(sock);
+		return 3;
+	}
+
+	if ((sockfd = fdopen(sock, "r+")) == NULL) {
+		close(sock);
+		return 5;
+	}
+
+	if (fputs(req_buf, sockfd) == EOF) {
+		fclose(sockfd);
+		close(sock);
+		return 5;
+	}
+
+	writeit = 0;
+	while (fgets(buffer, buf_len, sockfd) != NULL) {
+		/* ignore http headers */
+		if (writeit == 0) {
+			if (buffer[0] == '\r' || buffer[0] == '\n')
+				writeit = 1;
+		} else {
+			printf("%s", buffer);
+		}
+	}
+	fclose(sockfd);
+	close(sock);
+	return 0;
+}
+
+static int insert_resource(u64 node_uuid, u64 res_uuid, u64 res_size) {
+	char *req_buf;
+        ssprintf( req_buf, "GET http://"HTTP_HOST"/cgi-bin/insert_usage.pl?"
+		  "nu="U64"&ru="U64"&rs="U64" HTTP/1.0\n\n",
+		  node_uuid, res_uuid, res_size);
+	return make_get_request(req_buf);
+}
+
+/* Ensure that the node is counted on http://usage.drbd.org
+ */
+void uc_node(enum usage_count_type type)
+{
+	struct node_info ni;
+	char *req_buf;
+	u32 current;
+	int send = 0;
+	int update = 0;
+	char answer[10];
+
+	if( type == UC_NO ) return;
+
+	current = numeric_version_code(REL_VERSION);
+
+	if( ! read_node_id(&ni) ) {
+		get_random_bytes(&ni.node_uuid,sizeof(ni.node_uuid));
+		ni.version_code = current;
+		send = 1;
+	} else {
+		// read_node_id() was successull
+		if (ni.version_code != current) {
+			ni.version_code = current;
+			update = 1;
+			send = 1;
+		}
+	}
+
+	if(!send) return;
+	
+	if (type == UC_ASK ) {
+		printf(
+"\n"
+"\t\t--== This is %s of DRBD ==--\n"
+"Please take part in the global DRBD usage count at http://"HTTP_HOST".\n\n"
+"The conter works completely anonymous. A random number gets created on\n"
+"you machine, and that randomer number (as identifier for this machine) and\n"
+"DRBD's version number are sent to "HTTP_HOST".\n\n"
+"The benifits for you are:\n"
+" * As a respose to your data, the server ("HTTP_HOST") will tell you\n"
+"   how many users before your have installed this version (%s).\n"
+" * With a high counter the DRBD developers have a high motivation to\n"
+"   continue development of the software.\n\n"
+"The following string will be send to the server:\n"
+"http://"HTTP_HOST"/cgi-bin/insert_usage.pl?nu="U64"&nv="U32"\n\n"
+"In case you want to participate but know that this machines is firewalled\n"
+"simply issue the query string with your favourite web browser or wget\n\n"
+"You can control all this by setting 'usage-count' in the globals section\n"
+"of your drbd.conf\n\n"
+"Just press [enter] or enter 'no'[enter] to opt out: ",
+			update ? "an update" : "a new installation",
+			REL_VERSION,ni.node_uuid, ni.version_code);
+		fgets(answer,9,stdin);
+		if(!strcmp(answer,"no")) send = 0;
+	}
+
+        ssprintf(req_buf,"GET http://"HTTP_HOST"/cgi-bin/insert_usage.pl?"
+		 "nu="U64"&nv="U32" HTTP/1.0\n\n",
+		 ni.node_uuid, ni.version_code);
+
+	if (send) {
+		write_node_id(&ni);
+
+		printf(
+"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+"  --==  Thank you for participating in the global usage survey  ==--\n"
+"The server's response is:\n\n");
+		make_get_request(req_buf);
+		printf(
+"\n"
+"In the future drbdadm will only contact "HTTP_HOST" when you update\n"
+"DRBD or when you use 'drbdadm create-md'. Of course it will continue\n"
+"to ask you for confirmation as long as 'usage-count' is at its default\n"
+"value of 'ask'.\n\n"
+"Just press [enter] to continue: ");
+		fgets(answer,9,stdin);
+	}
+}



More information about the drbd-cvs mailing list