This wiki is obsolete, see the NorduGrid web pages for up to date information.
Developing services
Developing services
Security
Linux FHS
The Linux Filesystem Hierarchy Standard dictates where files should go
init.d
logrotate.d
cron.d
Signals
Signals are sent from users or the system to your service, the important ones that need to be handled are:
- HUP - when it should reload configurations and reopen files (logs, etc)
- TERM - the nice way of terminating a program, handling this needs to end up with a exit(0) or exit(1)
In C
Minimal program for handling a SIGHUP
#include <signal.h> // signal handling in this header #include <stdio.h> void signal_handler(int sig){ switch(sig){ case SIGHUP: printf("hangup signal catched\n"); break; } } int main(int argc, char** argv){ signal(SIGHUP,signal_handler); /* catch hangup signal */ while(1) sleep(1); }
In Perl
In Python
In Bash/Sh
Creating a Daemon/Service
Adding a new service to the code tree
Starting a new component be it a new service or new protocol etc. Is quite easy though there are some rules / guideline one must follow. We will use an example of a new service but the instructions here can be applied to most other parts of the code. First find the appropriate location (for services it is in src/services):
cd src/services mkdir myservice cd myservice
The first thing you should do is to add a README file. The README file should give a short explanation about the services. The README file is mandatory. The second file you should add is Makefile.am. This file is used by Automake (part of Autotools) and is a recipe for how to build your component. Here is a good starting template:
# For Unit testing SUBDIRS = $(TEST_DIR) DIST_SUBDIRS = test # The service pkglib_LTLIBRARIES = libmyservice.la libmyservice_la_SOURCES = myservice.cpp myservice.h libmyservice_la_CXXFLAGS = $(GLIBMM_CFLAGS) $(LIBXML2_CFLAGS) -I$(top_srcdir)/include libmyservice_la_LIBADD = $(top_srcdir)/src/hed/libs/loader/libarcloader.la $(top_srcdir)/src/hed/libs/message/libarcmessage.la $(top_srcdir)/src/hed/libs/security/libarcsecurity.la \ $(top_srcdir)/src/hed/libs/common/libarccommon.la $(GLIBMM_LIBS) $(LIBXML2_LIBS) libmyservice_la_LDFLAGS = -no-undefined -avoid-version -module
The first paragraph is needed for unit testing which is explained on ARC1/Unit Testing. The second paragraph is the recipe for creating the "myservice" service plugin.
Once we are ready to build the service we must inform Autotools about the new component. This is done in the toplevel configure.ac. Towards the bottom of this file there is a line starting with
AC_CONFIG_FILES
List your directories with appended "/Makefile" below in the list:
... src/services/Makefile src/services/test/Makefile ...
Autotools will create Makefile.in and Makefile from your Makefile.am recipe.
We have created a service which installs a file through the line:
pkglib_LTLIBRARIES = libmyservice.la
We need to explicitly tell the packaging tools about this file. For RPM packaging this is done in the toplevel:
nordugrid-arc.spec.in
while for DEB packaging there is a file per service:
debian/nordugrid-arc-newservice.install
We should now be ready to test that our service is properly integrated in the build structure. Go to the top-level directory and do:
./autogen.sh # Needed if you modify Makefile.am ./configure make make check # Run the Unit tests make install DESTDIR=/tmp/myinstall
If all went well you should be able to find your new service installed under /tmp/myinstall.
Please respect your fellow coders and make sure that your service compiles correctly.
Example code for a new service within HED
HED is the Hosting Environment Daemon and is a container for services. See "The Hosting Environment of the Advanced Resource Connector middleware" for a general description of it. For configuration information and how Message Chain Components (MCCs) work please read "WS-ARC service configuration manual".
At a minimum a HED service must:
- Define a sub-class of RegisteredService
- Implement the process() method - this is the method that is called when the service is invoked
- Provide the factory method get_service which enables HED to create an instance of the service
- Define the PLUGINS_TABLE_NAME array with this service
- Optionally define a RegistrationCollector() method to enable the service to be registered in the information system
The following code is a minimal example of such a service
NewService.h
#include <arc/infosys/RegisteredService.h> #include <arc/message/Message.h> #include <arc/XMLNode.h> #include <string> namespace NewService { class NewService: public Arc::RegisteredService { public: NewService(Arc::Config *cfg); virtual Arc::MCC_Status process(Arc::Message &inmsg, Arc::Message &outmsg); bool RegistrationCollector(Arc::XMLNode &doc); }; } // namespace NewService
NewService.cpp
#include <arc/message/MessageAttributes.h> #include <arc/message/PayloadRaw.h> #include <arc/message/PayloadStream.h> namespace NewService { static Arc::Plugin *get_service(Arc::PluginArgument* arg) { Arc::ServicePluginArgument* srvarg = arg?dynamic_cast<Arc::ServicePluginArgument*>(arg):NULL; if(!srvarg) return NULL; NewService* s = new NewService((Arc::Config*)(*srvarg)); return s; } NewService::NewService(Arc::Config *cfg) : RegisteredService(cfg) {} Arc::MCC_Status NewService::process(Arc::Message &inmsg, Arc::Message &outmsg) { return Arc::MCC_Status(Arc::STATUS_OK); } bool NewService::RegistrationCollector(Arc::XMLNode &doc) { Arc::NS isis_ns; isis_ns["isis"] = "http://www.nordugrid.org/schemas/isis/2008/08"; Arc::XMLNode regentry(isis_ns, "RegEntry"); regentry.NewChild("SrcAdv").NewChild("Type") = "org.nordugrid.execution.newservice"; regentry.New(doc); return true; } } // namespace NewService Arc::PluginDescriptor PLUGINS_TABLE_NAME[] = { { "newservice", "HED:SERVICE", 0, &NewService::get_service }, { NULL, NULL, 0, NULL } };
The Arc::Config object passed to the constructor contains configuration information for that service. One persistent instance of the service class is created upon HED startup and is used for the lifetime of the HED process. When a client invokes the service, HED calls the process method of the service instance. The inmsg Message in process() contains the XML message sent to the service from the client and in this method the actions should be defined depending on the client requests. outmsg is what is sent back to the client and should be filled appropriately. For working examples of services one can browse the src/services folder of the ARC subversion repository.