More controller work, and some RedHat fixes.

This commit is contained in:
Adam Ierymenko 2016-06-10 08:26:27 -07:00
parent 9898066b47
commit acbe8ad398
6 changed files with 103 additions and 39 deletions

View file

@ -66,8 +66,8 @@
// Stored in database as schemaVersion key in Config. // Stored in database as schemaVersion key in Config.
// If not present, database is assumed to be empty and at the current schema version // If not present, database is assumed to be empty and at the current schema version
// and this key/value is added automatically. // and this key/value is added automatically.
#define ZT_NETCONF_SQLITE_SCHEMA_VERSION 2 #define ZT_NETCONF_SQLITE_SCHEMA_VERSION 3
#define ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR "2" #define ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR "3"
// API version reported via JSON control plane // API version reported via JSON control plane
#define ZT_NETCONF_CONTROLLER_API_VERSION 1 #define ZT_NETCONF_CONTROLLER_API_VERSION 1
@ -159,7 +159,9 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
if (schemaVersion == -1234) { if (schemaVersion == -1234) {
sqlite3_close(_db); sqlite3_close(_db);
throw std::runtime_error("SqliteNetworkController schemaVersion not found in Config table (init failure?)"); throw std::runtime_error("SqliteNetworkController schemaVersion not found in Config table (init failure?)");
} else if (schemaVersion == 1) { }
if (schemaVersion < 2) {
// Create NodeHistory table to upgrade from version 1 to version 2 // Create NodeHistory table to upgrade from version 1 to version 2
if (sqlite3_exec(_db, if (sqlite3_exec(_db,
"CREATE TABLE NodeHistory (\n" "CREATE TABLE NodeHistory (\n"
@ -174,19 +176,46 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
" networkRequestMetaData VARCHAR(1024),\n" " networkRequestMetaData VARCHAR(1024),\n"
" fromAddress VARCHAR(128)\n" " fromAddress VARCHAR(128)\n"
");\n" ");\n"
"\n"
"CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId);\n" "CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId);\n"
"CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n" "CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n"
"CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n" "CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n"
"\n"
"UPDATE \"Config\" SET \"v\" = 2 WHERE \"k\" = 'schemaVersion';\n" "UPDATE \"Config\" SET \"v\" = 2 WHERE \"k\" = 'schemaVersion';\n"
,0,0,0) != SQLITE_OK) { ,0,0,0) != SQLITE_OK) {
char err[1024]; char err[1024];
Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 2: %s",sqlite3_errmsg(_db)); Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 2: %s",sqlite3_errmsg(_db));
sqlite3_close(_db); sqlite3_close(_db);
throw std::runtime_error(err); throw std::runtime_error(err);
} else {
schemaVersion = 2;
} }
} else if (schemaVersion != ZT_NETCONF_SQLITE_SCHEMA_VERSION) { }
if (schemaVersion < 3) {
// Create Route table to upgrade from version 2 to version 3, also drop obsolete Gateway table (which was never actually used)
if (sqlite3_exec(_db,
"DROP TABLE Gateway;\n"
"CREATE TABLE Route (\n"
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"
" target blob(16) NOT NULL,\n"
" via blob(16) NOT NULL,\n"
" targetNetmaskBits integer NOT NULL,\n"
" ipVersion integer NOT NULL,\n"
" flags integer NOT NULL,\n"
" metric integer NOT NULL\n"
");\n"
"CREATE INDEX Route_networkId ON Route (networkId);\n"
"UPDATE \"Config\" SET \"v\" = 3 WHERE \"k\" = 'schemaVersion';\n"
,0,0,0) != SQLITE_OK) {
char err[1024];
Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 2: %s",sqlite3_errmsg(_db));
sqlite3_close(_db);
throw std::runtime_error(err);
} else {
schemaVersion = 3;
}
}
if (schemaVersion != ZT_NETCONF_SQLITE_SCHEMA_VERSION) {
sqlite3_close(_db); sqlite3_close(_db);
throw std::runtime_error("SqliteNetworkController database schema version mismatch"); throw std::runtime_error("SqliteNetworkController database schema version mismatch");
} }
@ -260,6 +289,11 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ?",-1,&_sDeleteAllNetworkMembers,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ?",-1,&_sDeleteAllNetworkMembers,(const char **)0) != SQLITE_OK)
/* Route */
||(sqlite3_prepare_v2(_db,"INSERT INTO Route (networkId,target,via,targetNetmaskBits,ipVersion,flags,metric) VALUES (?,?,?,?,?,?,?)",-1,&_sCreateRoute,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT target,via,targetNetmaskBits,ipVersion,flags,metric FROM \"Route\" WHERE networkId = ?",-1,&_sGetRoutes,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"DELETE FROM \"Route\" WHERE networkId = ?",-1,&_sDeleteRoutes,(const char **)0) != SQLITE_OK)
/* Config */ /* Config */
||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK)
@ -343,6 +377,9 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sDeleteMember); sqlite3_finalize(_sDeleteMember);
sqlite3_finalize(_sDeleteAllNetworkMembers); sqlite3_finalize(_sDeleteAllNetworkMembers);
sqlite3_finalize(_sDeleteNetwork); sqlite3_finalize(_sDeleteNetwork);
sqlite3_finalize(_sCreateRoute);
sqlite3_finalize(_sGetRoutes);
sqlite3_finalize(_sDeleteRoute);
sqlite3_finalize(_sIncrementMemberRevisionCounter); sqlite3_finalize(_sIncrementMemberRevisionCounter);
sqlite3_finalize(_sGetConfig); sqlite3_finalize(_sGetConfig);
sqlite3_finalize(_sSetConfig); sqlite3_finalize(_sSetConfig);

View file

@ -178,6 +178,9 @@ private:
sqlite3_stmt *_sDeleteMember; sqlite3_stmt *_sDeleteMember;
sqlite3_stmt *_sDeleteAllNetworkMembers; sqlite3_stmt *_sDeleteAllNetworkMembers;
sqlite3_stmt *_sDeleteNetwork; sqlite3_stmt *_sDeleteNetwork;
sqlite3_stmt *_sCreateRoute;
sqlite3_stmt *_sGetRoutes;
sqlite3_stmt *_sDeleteRoutes;
sqlite3_stmt *_sIncrementMemberRevisionCounter; sqlite3_stmt *_sIncrementMemberRevisionCounter;
sqlite3_stmt *_sGetConfig; sqlite3_stmt *_sGetConfig;
sqlite3_stmt *_sSetConfig; sqlite3_stmt *_sSetConfig;

View file

@ -51,15 +51,6 @@ CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId);
CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId); CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);
CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime); CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);
CREATE TABLE Gateway (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
ip blob(16) NOT NULL,
ipVersion integer NOT NULL DEFAULT(4),
metric integer NOT NULL DEFAULT(0)
);
CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);
CREATE TABLE IpAssignment ( CREATE TABLE IpAssignment (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE, nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE,
@ -94,6 +85,18 @@ CREATE TABLE Member (
CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision); CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);
CREATE TABLE Route (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
target blob(16) NOT NULL,
via blob(16) NOT NULL,
targetNetmaskBits integer NOT NULL,
ipVersion integer NOT NULL,
flags integer NOT NULL,
metric integer NOT NULL
);
CREATE INDEX Route_networkId ON Route (networkId);
CREATE TABLE Relay ( CREATE TABLE Relay (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
address char(10) NOT NULL, address char(10) NOT NULL,

View file

@ -52,15 +52,6 @@
"CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n"\ "CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n"\
"CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n"\ "CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n"\
"\n"\ "\n"\
"CREATE TABLE Gateway (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" ip blob(16) NOT NULL,\n"\
" ipVersion integer NOT NULL DEFAULT(4),\n"\
" metric integer NOT NULL DEFAULT(0)\n"\
");\n"\
"\n"\
"CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);\n"\
"\n"\
"CREATE TABLE IpAssignment (\n"\ "CREATE TABLE IpAssignment (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE,\n"\ " nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE,\n"\
@ -95,6 +86,18 @@
"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ "CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
"CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);\n"\ "CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);\n"\
"\n"\ "\n"\
"CREATE TABLE Route (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" target blob(16) NOT NULL,\n"\
" targetNetmaskBits integer NOT NULL,\n"\
" via blob(16) NOT NULL,\n"\
" ipVersion integer NOT NULL,\n"\
" flags integer NOT NULL,\n"\
" metric integer NOT NULL\n"\
");\n"\
"\n"\
"CREATE INDEX Route_networkId ON Route (networkId);\n"\
"\n"\
"CREATE TABLE Relay (\n"\ "CREATE TABLE Relay (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" address char(10) NOT NULL,\n"\ " address char(10) NOT NULL,\n"\

View file

@ -9,13 +9,14 @@
# #
# Targets # Targets
# one: zerotier-one and symlinks (cli and idtool) # one: zerotier-one and symlinks (cli and idtool)
# doc: builds manpages, requires rst2man somewhere in PATH # manpages: builds manpages, requires 'ronn' or nodeJS (will use either)
# all: builds 'one' # all: builds 'one' and 'manpages'
# selftest: zerotier-selftest # selftest: zerotier-selftest
# debug: builds 'one' and 'selftest' with tracing and debug flags # debug: builds 'one' and 'selftest' with tracing and debug flags
# installer: builds installers and packages (RPM/DEB/etc.) if possible
# official: cleans and then builds 'one', 'installer', and 'doc'
# clean: removes all built files, objects, other trash # clean: removes all built files, objects, other trash
# distclean: removes a few other things that might be present
# debian: build DEB packages; deb dev tools must be present
# redhat: build RPM packages; rpm dev tools must be present
# #
# Automagically pick clang or gcc, with preference for clang # Automagically pick clang or gcc, with preference for clang
@ -36,7 +37,8 @@ DESTDIR?=
include objects.mk include objects.mk
# On Linux we auto-detect the presence of some libraries # On Linux we auto-detect the presence of some libraries and if present we
# link against the system version. This works with our package build images.
ifeq ($(wildcard /usr/include/lz4.h),) ifeq ($(wildcard /usr/include/lz4.h),)
OBJS+=ext/lz4/lz4.o OBJS+=ext/lz4/lz4.o
else else
@ -56,22 +58,24 @@ else
DEFS+=-DZT_USE_SYSTEM_JSON_PARSER DEFS+=-DZT_USE_SYSTEM_JSON_PARSER
endif endif
ifeq ($(ZT_OFFICIAL_RELEASE),1)
DEFS+=-DZT_OFFICIAL_RELEASE
ZT_USE_MINIUPNPC=1
endif
ifeq ($(ZT_USE_MINIUPNPC),1) ifeq ($(ZT_USE_MINIUPNPC),1)
DEFS+=-DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
OBJS+=osdep/PortMapper.o OBJS+=osdep/PortMapper.o
# We always use ext/miniupnpc because versions that ship with various Linux distributions are too old DEFS+=-DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
# Right now auto-detect and use of system miniupnpc is disabled since the
# versions that ship with various Linux distributions are pretty much all
# ancient or broken.
#ifeq ($(wildcard /usr/include/miniupnpc/miniupnpc.h),) #ifeq ($(wildcard /usr/include/miniupnpc/miniupnpc.h),)
OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o
#else #else
# LDLIBS+=-lminiupnpc # LDLIBS+=-lminiupnpc
#endif #endif
# libnatpmp on the other hand is safe to auto-detect and use -- the two
# libraries are by the same author but are separate.
ifeq ($(wildcard /usr/include/natpmp.h),) ifeq ($(wildcard /usr/include/natpmp.h),)
OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o
else else
@ -127,6 +131,7 @@ one: $(OBJS) service/OneService.o one.o osdep/LinuxEthernetTap.o
ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-idtool
ln -sf zerotier-one zerotier-cli ln -sf zerotier-one zerotier-cli
# This is going away -- netcon is becoming the ZeroTier SDK and is going into a separate repo
netcon: $(OBJS) netcon: $(OBJS)
rm -f *.o rm -f *.o
# Need to selectively rebuild one.cpp and OneService.cpp with ZT_SERVICE_NETCON and ZT_ONE_NO_ROOT_CHECK defined, and also NetconEthernetTap # Need to selectively rebuild one.cpp and OneService.cpp with ZT_SERVICE_NETCON and ZT_ONE_NO_ROOT_CHECK defined, and also NetconEthernetTap
@ -146,6 +151,8 @@ selftest: $(OBJS) selftest.o
manpages: FORCE manpages: FORCE
cd doc ; ./build.sh cd doc ; ./build.sh
doc: manpages
clean: FORCE clean: FORCE
rm -rf *.so *.o netcon/*.a node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest zerotier-netcon-service build-* ZeroTierOneInstaller-* *.deb *.rpm .depend netcon/.depend doc/*.1 doc/*.2 doc/*.8 debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one rm -rf *.so *.o netcon/*.a node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest zerotier-netcon-service build-* ZeroTierOneInstaller-* *.deb *.rpm .depend netcon/.depend doc/*.1 doc/*.2 doc/*.8 debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one
find netcon -type f \( -name '*.o' -o -name '*.so' -o -name '*.1.0' -o -name 'zerotier-one' -o -name 'zerotier-cli' -o -name 'zerotier-netcon-service' \) -delete find netcon -type f \( -name '*.o' -o -name '*.so' -o -name '*.1.0' -o -name 'zerotier-one' -o -name 'zerotier-cli' -o -name 'zerotier-netcon-service' \) -delete
@ -154,10 +161,16 @@ clean: FORCE
distclean: clean distclean: clean
rm -rf doc/node_modules rm -rf doc/node_modules
realclean: distclean
debug: FORCE debug: FORCE
make ZT_DEBUG=1 one make ZT_DEBUG=1 one
make ZT_DEBUG=1 selftest make ZT_DEBUG=1 selftest
# Note: keep the symlinks in /var/lib/zerotier-one to the binaries since these
# provide backward compatibility with old releases where the binaries actually
# lived here. Folks got scripts.
install: FORCE install: FORCE
mkdir -p $(DESTDIR)/usr/sbin mkdir -p $(DESTDIR)/usr/sbin
rm -f $(DESTDIR)/usr/sbin/zerotier-one rm -f $(DESTDIR)/usr/sbin/zerotier-one
@ -183,6 +196,9 @@ install: FORCE
cat doc/zerotier-cli.1 | gzip -9 >$(DESTDIR)/usr/share/man/man1/zerotier-cli.1.gz cat doc/zerotier-cli.1 | gzip -9 >$(DESTDIR)/usr/share/man/man1/zerotier-cli.1.gz
cat doc/zerotier-idtool.1 | gzip -9 >$(DESTDIR)/usr/share/man/man1/zerotier-idtool.1.gz cat doc/zerotier-idtool.1 | gzip -9 >$(DESTDIR)/usr/share/man/man1/zerotier-idtool.1.gz
# Uninstall preserves identity.public and identity.secret since the user might
# want to save these. These are your ZeroTier address.
uninstall: FORCE uninstall: FORCE
rm -f $(DESTDIR)/var/lib/zerotier-one/zerotier-one rm -f $(DESTDIR)/var/lib/zerotier-one/zerotier-one
rm -f $(DESTDIR)/var/lib/zerotier-one/zerotier-cli rm -f $(DESTDIR)/var/lib/zerotier-one/zerotier-cli
@ -198,6 +214,8 @@ uninstall: FORCE
rm -f $(DESTDIR)/usr/share/man/man1/zerotier-idtool.1.gz rm -f $(DESTDIR)/usr/share/man/man1/zerotier-idtool.1.gz
rm -f $(DESTDIR)/usr/share/man/man1/zerotier-cli.1.gz rm -f $(DESTDIR)/usr/share/man/man1/zerotier-cli.1.gz
# These are just for convenience for building Linux packages
debian: distclean debian: distclean
debuild -I -i -us -uc debuild -I -i -us -uc

View file

@ -67,13 +67,13 @@ cp debian/zerotier-one.service $RPM_BUILD_ROOT%{_unitdir}/%{name}.service
%license LICENSE.GPL-3 %license LICENSE.GPL-3
%post %post
%systemd_post apache-httpd.service %systemd_post zerotier-one.service
%preun %preun
%systemd_preun apache-httpd.service %systemd_preun zerotier-one.service
%postun %postun
%systemd_postun_with_restart apache-httpd.service %systemd_postun_with_restart zerotier-one.service
%changelog %changelog
* Wed Jun 08 2016 François Kooman <fkooman@tuxed.net> - 1.1.5-0.3 * Wed Jun 08 2016 François Kooman <fkooman@tuxed.net> - 1.1.5-0.3