20794905 system-repository htcacheclean should become a scheduled service
authorTim Foster <tim.s.foster@oracle.com>
Fri, 05 Jun 2015 12:03:49 +1200
changeset 3216 8b56fb6976b3
parent 3215 69e16273b1e3
child 3217 e8297210afb4
20794905 system-repository htcacheclean should become a scheduled service 15758476 system-repository can be online when no repository is available 15744195 system-repo refresh shouldn't trigger htcacheclean 15739450 two instances of htcacheclean still running 15723062 killing htcacheclean manually puts system-repo into maintenance on 15718055 htcacheclean is running all the time
src/pkg/manifests/package:pkg:system-repository.p5m
src/setup.py
src/svc/pkg-sysrepo-cache.xml
src/svc/pkg-system-repository.xml
src/svc/svc-pkg-sysrepo
src/svc/svc-pkg-sysrepo-cache
--- a/src/pkg/manifests/package:pkg:system-repository.p5m	Thu Jun 04 12:45:09 2015 -0700
+++ b/src/pkg/manifests/package:pkg:system-repository.p5m	Fri Jun 05 12:03:49 2015 +1200
@@ -39,8 +39,10 @@
 dir  path=lib/svc/manifest
 dir  path=lib/svc/manifest/application
 dir  path=lib/svc/manifest/application/pkg
+file path=lib/svc/manifest/application/pkg/pkg-sysrepo-cache.xml
 file path=lib/svc/manifest/application/pkg/pkg-system-repository.xml
 file path=lib/svc/method/svc-pkg-sysrepo
+file path=lib/svc/method/svc-pkg-sysrepo-cache
 dir  path=usr
 file path=usr/lib/pkg.sysrepo mode=0755
 dir  path=usr/share/man/ja_JP.UTF-8/man1m
--- a/src/setup.py	Thu Jun 04 12:45:09 2015 -0700
+++ b/src/setup.py	Fri Jun 05 12:03:49 2015 +1200
@@ -173,6 +173,8 @@
                     'svc-pkg-repositories-setup'],
                 ['svc/svc-pkg-server', 'svc-pkg-server'],
                 ['svc/svc-pkg-sysrepo', 'svc-pkg-sysrepo'],
+                ['svc/svc-pkg-sysrepo-cache',
+                    'svc-pkg-sysrepo-cache'],
                 ],
         svc_share_dir: [
                 ['svc/pkg5_include.sh', 'pkg5_include.sh'],
@@ -381,6 +383,7 @@
         'svc/pkg-repositories-setup.xml',
         'svc/pkg-server.xml',
         'svc/pkg-system-repository.xml',
+        'svc/pkg-sysrepo-cache.xml',
         'svc/zoneproxy-client.xml',
         'svc/zoneproxyd.xml'
         ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/pkg-sysrepo-cache.xml	Fri Jun 05 12:03:49 2015 +1200
@@ -0,0 +1,143 @@
+<?xml version="1.0"?>
+<!--
+	CDDL HEADER START
+
+	The contents of this file are subject to the terms of the
+	Common Development and Distribution License (the "License").
+	You may not use this file except in compliance with the License.
+
+	You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+	or http://www.opensolaris.org/os/licensing.
+	See the License for the specific language governing permissions
+	and limitations under the License.
+
+	When distributing Covered Code, include this CDDL HEADER in each
+	file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+	If applicable, add the following below this CDDL HEADER, with the
+	fields enclosed by brackets "[]" replaced with your own identifying
+	information: Portions Copyright [yyyy] [name of copyright owner]
+
+	CDDL HEADER END
+
+	Copyright (c) 2015 Oracle and/or its affiliates.  All rights reserved.
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+-->
+
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+
+<!-- This service is responsible for periodically running the Apache
+     htcacheclean program to prune the system-repository cache down
+     to a required size -->
+<service_bundle type='manifest' name='pkg:sysrepo-cache-compact'>
+
+<service
+	name='application/pkg/sysrepo-cache-compact'
+	type='service'
+	version='1'>
+
+	<instance name='default' enabled='false'>
+		<!--
+		  Wait for network interfaces to be initialized.
+		-->
+		<dependency name='network'
+		    grouping='require_all'
+		    restart_on='none'
+		    type='service'>
+		    <service_fmri value='svc:/milestone/network:default'/>
+		</dependency>
+
+		<!--
+		  Wait for all local filesystems to be mounted.
+		-->
+		<dependency name='filesystem-local'
+		    grouping='require_all'
+		    restart_on='none'
+		    type='service'>
+		    <service_fmri
+			value='svc:/system/filesystem/local:default'/>
+		</dependency>
+
+		<!--
+		  Require the system-repository service. There's no
+		  point in running this service if the system-repository
+		  isn't around to actually populate the cache.
+
+		  Despite our using config properties from the system repository,
+		  since this is a scheduled service, if those properties change
+		  we pick them up during the next scheduled run - no need for a
+		  restart_on setting.
+		-->
+		<dependency name='sysrepo'
+		    grouping='require_all'
+		    restart_on='none'
+		    type='service'>
+		    <service_fmri
+			value='svc:/application/pkg/system-repository:default'/>
+		</dependency>
+
+		<!--
+		  Running the service every 3 months is likely to be enough.
+		   We choose an arbitrary hour to run the service at, but
+		  the specific time does not matter. If a system is
+		  offline at the time the service is due to run,
+		  'recover' will cause it to run when the system comes
+		  online again.
+		-->
+		<scheduled_method
+			interval='month'
+			frequency='3'
+			day_of_month='1'
+			hour='15'
+			recover='true'
+			exec='/lib/svc/method/svc-pkg-sysrepo-cache'
+			timeout_seconds='-1'>
+			<method_context>
+				<method_credential user='pkg5srv'
+				group='pkg5srv' />
+			</method_context>
+		</scheduled_method>
+
+		<property_group name='config' type='application'>
+			<stability value='Evolving' />
+			<!-- Note that this service uses the following
+			    properties from
+			    svc:/application/pkg/system-repository:default
+
+				config/cache_dir
+				config/cache_max
+
+			    We rely on pkg.sysrepo to validate the values for
+			    these settings, and certain cache_dir values may
+			    require configuration in the system-repository
+			    httpd.conf.
+			-->
+			</property_group>
+
+			<property_group name='general' type='framework'>
+				<propval name='action_authorization'
+				type='astring'
+				value='solaris.smf.manage.pkg-sysrepo' />
+				<propval name='value_authorization'
+				type='astring'
+				value='solaris.smf.value.pkg-sysrepo' />
+			</property_group>
+
+			<template>
+				<common_name>
+					<loctext xml:lang='C'>
+					IPS System Repository Cache Maintenance
+					</loctext>
+				</common_name>
+				<documentation>
+					<manpage title='pkg.sysrepo' section='1M' />
+				</documentation>
+			</template>
+		</instance>
+
+		<stability value='Evolving' />
+	</service>
+</service_bundle>
--- a/src/svc/pkg-system-repository.xml	Thu Jun 04 12:45:09 2015 -0700
+++ b/src/svc/pkg-system-repository.xml	Fri Jun 05 12:03:49 2015 +1200
@@ -19,7 +19,7 @@
 
 	CDDL HEADER END
 
-	Copyright (c) 2011, 2013 Oracle and/or its affiliates.  All rights reserved.
+	Copyright (c) 2011, 2015 Oracle and/or its affiliates.  All rights reserved.
 
 	NOTE:  This service manifest is not editable; its contents will
 	be overwritten by package or patch operations, including
@@ -107,63 +107,71 @@
 			exec='/lib/svc/method/svc-pkg-sysrepo refresh'
 			timeout_seconds='60' >
 			<method_context>
-             			<method_credential user='pkg5srv'
+				<method_credential user='pkg5srv'
 				group='pkg5srv' privileges='all' />
-		        </method_context>
+			</method_context>
 		</exec_method>
 
 
-                <property_group name='config' type='application'>
-                        <stability value='Evolving' />
-                        <!-- The port we listen on -->
-                        <propval name='port' type='count' value='1008' />
-                        <!-- The host we're running on -->
-                        <propval name='host' type='astring' value='127.0.0.1' />
-                        <!-- Where we store apache logs -->
-                        <propval name='log_dir' type='astring'
-                                value='/var/log/pkg/sysrepo' />
-                        <!-- Where we store runtime versions of our
+		<property_group name='config' type='application'>
+			<stability value='Evolving' />
+			<!-- The port we listen on -->
+			<propval name='port' type='count' value='1008' />
+			<!-- The host we're running on -->
+			<propval name='host' type='astring' value='127.0.0.1' />
+			<!-- Where we store apache logs -->
+			<propval name='log_dir' type='astring'
+				value='/var/log/pkg/sysrepo' />
+			<!-- Where we store runtime versions of our
 			 configuration -->
-                        <propval name='runtime_dir' type='astring'
+			<propval name='runtime_dir' type='astring'
 				value='/system/volatile/pkg/sysrepo' />
-                        <!-- Where we store our Mako templates for generating
+			<!-- Where we store our Mako templates for generating
 			 runtime configuration -->
-                        <propval name='template_dir' type='astring'
-                                value='/etc/pkg/sysrepo' />
-                        <!-- Where we store our sysrepo apache cache
-                        If cache_dir is set to the special value "None" then we
-                        do not perform caching.  If cache_dir is set to the
-                        special value "memory" we use an in-memory cache.
-                        -->
-                        <propval name='cache_dir' type='astring'
-                                value='/var/cache/pkg/sysrepo' />
-                        <!-- Our maximum cache size, expressed in MB -->
-                        <propval name='cache_max' type='count' value='2048' />
-                        <propval name='value_authorization' type='astring'
-                                value='solaris.smf.value.pkg-sysrepo' />
+			<propval name='template_dir' type='astring'
+				value='/etc/pkg/sysrepo' />
+			<!-- Where we store our sysrepo apache cache
+			If cache_dir is set to the special value "None" then we
+			do not perform caching.  If cache_dir is set to the
+			special value "memory" we use an in-memory cache.
+
+			Note that this property is consumed by
+			svc:/application/pkg/sysrepo-cache-compact
+			-->
+			<propval name='cache_dir' type='astring'
+				value='/var/cache/pkg/sysrepo' />
+			<!-- Our maximum cache size, expressed in MB
+
+			Note that this property is consumed by
+			svc:/application/pkg/sysrepo-cache-compact
+			-->
+			<propval name='cache_max' type='count' value='2048' />
+			<propval name='value_authorization' type='astring'
+				value='solaris.smf.value.pkg-sysrepo' />
 
 			<!-- If the system-repository itself should use web
 			proxies to gain access to pkg(5) repositories,
-                        specify those here in, the form http://<host>:[port] -->
+			specify those here in, the form http://<host>:[port]
+			-->
 			<propval name='http_proxy' type='astring' value='' />
 			<propval name='https_proxy' type='astring' value='' />
 
-                </property_group>
+		</property_group>
 
 		<property_group name='general' type='framework'>
 			<propval name='action_authorization'
-                            type='astring'
-                            value='solaris.smf.manage.pkg-sysrepo' />
+				type='astring'
+				value='solaris.smf.manage.pkg-sysrepo' />
 			<propval name='value_authorization'
-                            type='astring'
-                            value='solaris.smf.value.pkg-sysrepo' />
+				type='astring'
+				value='solaris.smf.value.pkg-sysrepo' />
 		</property_group>
 
 		<template>
 			<common_name>
-			    <loctext xml:lang='C'>
-                                IPS System Repository
-                            </loctext>
+				<loctext xml:lang='C'>
+				IPS System Repository
+				</loctext>
 			</common_name>
 			<documentation>
 				<manpage title='pkg.sysrepo' section='1M' />
--- a/src/svc/svc-pkg-sysrepo	Thu Jun 04 12:45:09 2015 -0700
+++ b/src/svc/svc-pkg-sysrepo	Fri Jun 05 12:03:49 2015 +1200
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved.
 #
 
 . /lib/svc/share/smf_include.sh
@@ -46,29 +46,29 @@
 export LD_LIBRARY_PATH
 
 getprop() {
-    PROPVAL=""
-    svcprop -q -p $1 ${SMF_FMRI}
-    if [ $? -eq 0 ] ; then
-        PROPVAL=`svcprop -p $1 ${SMF_FMRI}`
-        if [ "${PROPVAL}" = "\"\"" ] ; then
-            PROPVAL=""
-        fi
-        return
-    fi
-    return
+	PROPVAL=""
+	svcprop -q -p $1 ${SMF_FMRI}
+	if [ $? -eq 0 ] ; then
+		PROPVAL=$(svcprop -p $1 ${SMF_FMRI})
+		if [ "${PROPVAL}" = "\"\"" ] ; then
+			PROPVAL=""
+		fi
+		return
+	fi
+	return
 }
 
 check_failure() {
-    RESULT=$1
-    MESSAGE=$2
-    NON_FATAL=$3
-    if [ $RESULT -ne 0 ]; then
-        echo $MESSAGE
-	if [ -n "$NON_FATAL" ]; then
-		return
+	RESULT=$1
+	MESSAGE=$2
+	NON_FATAL=$3
+	if [ $RESULT -ne 0 ]; then
+		echo $MESSAGE
+		if [ -n "$NON_FATAL" ]; then
+			return
+		fi
+		exit $SMF_EXIT_ERR_FATAL
 	fi
-	exit $SMF_EXIT_ERR_FATAL
-    fi
 }
 
 run_sysrepo() {
@@ -79,83 +79,57 @@
 		SYSREPO_HTTPS_PROXY="-W ${https_proxy}"
 	fi
 
-        /usr/lib/pkg.sysrepo \
-               -R / \
-               -c ${SYSREPO_CACHE_DIR} \
-               -h ${SYSREPO_HOST} \
-               -l ${SYSREPO_LOG_DIR} \
-               -p ${SYSREPO_PORT} \
-               -r ${SYSREPO_RUNTIME_DIR} \
-               -s ${SYSREPO_CACHE_MAX} \
-               -t ${SYSREPO_TEMPLATE_DIR} \
-	       ${SYSREPO_HTTP_PROXY} \
-	       ${SYSREPO_HTTPS_PROXY}
-        check_failure $? "pkg.sysrepo: failed to create Apache configuration"
-}
-
-run_htcacheclean() {
-	# if we dropped to maintenance and are in the process of clearing
-	# that state,  we may have a htcacheclean processes hanging around.
-	kill_htcacheclean
-	if [ "${SYSREPO_CACHE_DIR}" != "None" ] && \
-	    [ "${SYSREPO_CACHE_DIR}" != "memory" ]; then
-               # Start a cache cleaning daemon, scanning every 2 weeks,
-               # being intelligent about only running if the cache has changed,
-               # limiting the cache to ${SYSREPO_CACHE_MAX} megabytes, being
-               # nice about scheduling and removing empty directories if
-               # necessary.
-	       interval=$((60 * 24 * 14))
-               /usr/apache2/2.2/bin/htcacheclean \
-                       -d${interval} -i -l ${SYSREPO_CACHE_MAX}M -n \
-                       -p ${SYSREPO_CACHE_DIR} \
-                       -P ${SYSREPO_CACHE_DIR}/../sysrepo_htcacheclean.pid \
-                       -t
-               check_failure $? "htcacheclean failed to run cleanly"
-       fi
-}
-
-kill_htcacheclean() {
-	if [ -f ${SYSREPO_CACHE_DIR}/../sysrepo_htcacheclean.pid ]; then
-                PID=$(< ${SYSREPO_CACHE_DIR}/../sysrepo_htcacheclean.pid)
-                /usr/bin/kill -TERM $PID
-                check_failure $? "failed to kill htcacheclean process $PID" \
-		    "not_fatal"
-        fi
+	# Despite using a scheduled service for the htcacheclean
+	# process, pkg.sysrepo is still used to check the
+	# $SYSREPO_CACHE_* variables for valid values.
+	# See svc:/application/pkg/system-repository-cache-maintenance
+	/usr/lib/pkg.sysrepo \
+	    -R / \
+	    -c ${SYSREPO_CACHE_DIR} \
+	    -h ${SYSREPO_HOST} \
+	    -l ${SYSREPO_LOG_DIR} \
+	    -p ${SYSREPO_PORT} \
+	    -r ${SYSREPO_RUNTIME_DIR} \
+	    -s ${SYSREPO_CACHE_MAX} \
+	    -t ${SYSREPO_TEMPLATE_DIR} \
+	    ${SYSREPO_HTTP_PROXY} \
+	    ${SYSREPO_HTTPS_PROXY}
+	check_failure $? "pkg.sysrepo: failed to create Apache configuration"
 }
 
 getprop config/host
 if [ "${PROPVAL}" != "" ] ; then
-        SYSREPO_HOST=${PROPVAL}
+	SYSREPO_HOST=${PROPVAL}
 fi
 
 getprop config/port
 if [ "${PROPVAL}" != "" ] ; then
-        SYSREPO_PORT=${PROPVAL}
+	SYSREPO_PORT=${PROPVAL}
 fi
 
 getprop config/log_dir
 if [ "${PROPVAL}" != "" ] ; then
-        SYSREPO_LOG_DIR=${PROPVAL}
+	SYSREPO_LOG_DIR=${PROPVAL}
 fi
 
 getprop config/template_dir
 if [ "${PROPVAL}" != "" ] ; then
-        SYSREPO_TEMPLATE_DIR=${PROPVAL}
+	SYSREPO_TEMPLATE_DIR=${PROPVAL}
 fi
 
 getprop config/runtime_dir
 if [ "${PROPVAL}" != "" ] ; then
-        SYSREPO_RUNTIME_DIR=${PROPVAL}
+	SYSREPO_RUNTIME_DIR=${PROPVAL}
 fi
 
 getprop config/cache_dir
 if [ "${PROPVAL}" != "" ] ; then
-        SYSREPO_CACHE_DIR=${PROPVAL}
+	SYSREPO_CACHE_DIR=${PROPVAL}
 fi
 
 getprop config/cache_max
 if [ "${PROPVAL}" != "" ] ; then
-        SYSREPO_CACHE_MAX=${PROPVAL}
+	SYSREPO_CACHE_MAX=${PROPVAL}
 fi
 
 getprop config/http_proxy
@@ -174,9 +148,8 @@
 	run_sysrepo
 	# drop privileges now that we've written our configuration
 	/usr/bin/ppriv -s E=basic,net_privaddr $$
-	run_htcacheclean
 	${HTTPD} -f ${SYSREPO_RUNTIME_DIR}/sysrepo_httpd.conf \
-            ${STARTUP_OPTIONS} -k ${cmd} 2>&1
+	    ${STARTUP_OPTIONS} -k ${cmd} 2>&1
  	check_failure $? "Server failed to start. Check the SMF service log or the error log at ${SYSREPO_LOG_DIR}/error_log for more information, if any."
 	;;
 "refresh")
@@ -185,17 +158,14 @@
 	# drop privileges now that we've written our configuration
 	/usr/bin/ppriv -s E=basic,net_privaddr $$
 	/usr/bin/pkill -USR1 -ox zoneproxyd
-	kill_htcacheclean
-	run_htcacheclean
 	${HTTPD} -f ${SYSREPO_RUNTIME_DIR}/sysrepo_httpd.conf \
-            ${STARTUP_OPTIONS} -k ${cmd} 2>&1
+	    ${STARTUP_OPTIONS} -k ${cmd} 2>&1
 	check_failure $? "Server failed to refresh. Check the SMF service log or the error log at ${SYSREPO_LOG_DIR}/error_log for more information, if any."
 	;;
 "stop")
 	cmd="stop"
-	kill_htcacheclean
 	${HTTPD} -f ${SYSREPO_RUNTIME_DIR}/sysrepo_httpd.conf \
-            ${STARTUP_OPTIONS} -k ${cmd} 2>&1
+	    ${STARTUP_OPTIONS} -k ${cmd} 2>&1
 	check_failure $? "Server failed to stop. Check the SMF service log  or the error log at ${SYSREPO_LOG_DIR}/error_log for more information, if any."
 	;;
 *)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/svc/svc-pkg-sysrepo-cache	Fri Jun 05 12:03:49 2015 +1200
@@ -0,0 +1,95 @@
+#!/sbin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+#
+
+. /lib/svc/share/smf_include.sh
+
+getprop() {
+	PROPVAL=""
+	if [ -z "$2" ]; then
+		FMRI=svc:/application/pkg/system-repository:default
+	else
+		FMRI=${SMF_FMRI}
+	fi
+	svcprop -q -p $1 ${FMRI}
+	if [ $? -eq 0 ] ; then
+		PROPVAL=$(svcprop -p $1 ${FMRI})
+		if [ "${PROPVAL}" = "\"\"" ] ; then
+			PROPVAL=""
+		fi
+		return
+	fi
+}
+
+check_failure() {
+	RESULT=$1
+	MESSAGE=$2
+	NON_FATAL=$3
+	if [ $RESULT -ne 0 ]; then
+		echo $MESSAGE
+		if [ -n "$NON_FATAL" ]; then
+			return
+		fi
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+}
+
+run_htcacheclean() {
+	if [ "${SYSREPO_CACHE_DIR}" != "None" ] && [ "${SYSREPO_CACHE_DIR}" != "memory" ]; then
+		# Start a cache cleaning process, limiting the cache to
+		# ${SYSREPO_CACHE_MAX} megabytes, being nice about
+		# scheduling and removing empty directories if needed.
+		/usr/apache2/2.2/bin/htcacheclean \
+		   -l ${SYSREPO_CACHE_MAX}M -n \
+		    -p ${SYSREPO_CACHE_DIR} \
+		   -P ${SYSREPO_CACHE_DIR}/../sysrepo_htcacheclean.pid \
+		   -t
+		check_failure $? "htcacheclean failed to run cleanly"
+	fi
+}
+
+kill_htcacheclean() {
+	if [ -f ${SYSREPO_CACHE_DIR}/../sysrepo_htcacheclean.pid ]; then
+		PID=$(< ${SYSREPO_CACHE_DIR}/../sysrepo_htcacheclean.pid)
+		echo "Previous htcacheclean pid file found - killing process $PID"
+		/usr/bin/kill -TERM $PID
+		check_failure $? "failed to kill htcacheclean process $PID" \
+		    "not_fatal"
+	fi
+}
+
+getprop config/cache_dir
+if [ "${PROPVAL}" != "" ] ; then
+	SYSREPO_CACHE_DIR=${PROPVAL}
+fi
+
+getprop config/cache_max
+if [ "${PROPVAL}" != "" ] ; then
+	SYSREPO_CACHE_MAX=${PROPVAL}
+fi
+
+kill_htcacheclean
+run_htcacheclean
+
+exit $SMF_EXIT_OK