Merge lp:~marcoceppi/charms/precise/wordpress/trunk into lp:charms/wordpress
- Precise Pangolin (12.04)
- trunk
- Merge into trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Mark Mims | ||||||||
Approved revision: | no longer in the source branch. | ||||||||
Merged at revision: | 55 | ||||||||
Proposed branch: | lp:~marcoceppi/charms/precise/wordpress/trunk | ||||||||
Merge into: | lp:charms/wordpress | ||||||||
Diff against target: |
2597 lines (+2340/-56) (has conflicts) 24 files modified
README.md (+152/-0) config.yaml (+26/-0) copyright (+1/-1) files/_debug/apc.php (+1364/-0) files/_debug/info.php (+3/-0) files/charm/nginx/etc_nginx_nginx.conf (+58/-0) files/charm/nginx/etc_nginx_sites-enabled_loadbalancer (+51/-0) files/charm/nginx/etc_nginx_sites-enabled_wordpress (+72/-0) files/charm/php/php5-fpm_pool.d_www.conf (+41/-0) files/charm/php/php5_conf.d_apc.ini (+13/-0) hooks/config-changed (+54/-0) hooks/db-relation-changed (+94/-46) hooks/db-relation-departed (+5/-0) hooks/install (+56/-1) hooks/loadbalancer-relation-joined (+124/-0) hooks/nfs-relation-changed (+28/-0) hooks/nfs-relation-departed (+20/-0) hooks/restart (+4/-0) hooks/start (+3/-0) hooks/stop (+5/-2) hooks/upgrade-charm (+11/-0) inc/common (+139/-0) metadata.yaml (+12/-6) revision (+4/-0) Text conflict in hooks/db-relation-changed Text conflict in metadata.yaml Text conflict in revision |
||||||||
To merge this branch: | bzr merge lp:~marcoceppi/charms/precise/wordpress/trunk | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mark Mims (community) | Approve | ||
charmers | Pending | ||
Benjamin Kerensa | Pending | ||
Review via email: mp+120559@code.launchpad.net |
This proposal supersedes a proposal from 2012-08-07.
Commit message
Description of the change
There are a great many changes made to this charm, I will try to sum them up:
DO ALL THE THINGS THE OMGUBUNTU SITE DOES
Remove all the OMG! Ubuntu specific items
Allow for the use of NFS mounts to share data for lazy bloggers who are popular
Provide three configuration options for users: bare, single, optimized
Benjamin Kerensa (bkerensa) wrote : Posted in a previous version of this proposal | # |
Mark Mims (mark-mims) wrote : Posted in a previous version of this proposal | # |
Ok, here's a static review: This is an _example_ charm we'll use in charmschools and demos, so I'll have more stuff to say than when reviewing a normal charm :)
# things to change
- love the config and especially the config-changed hook... it's very simple, organized, and demoable! Please put explicit values into config.yaml... please don't make me guess if I should put `Optimized` or `optimized`
- so `charm proof` gives `I: relation shared-fs has no hooks`. I understand the desire to add a more general relation than nfs, but please remove this metadata until it's implemented to keep it clean and simple for people to read (demo charm)
- instead of `files/
- the `stop` hook references omgbackup... that's great but make it generic please
- I'd love to see some of your `files/charm` contents be actual templates where more stuff is externalized via config. e.g., ports and stuff. Well, ok... after looking some more, some of this stuff will *need* to be parametrized... i.e., there're urls littering the static config files. Those need to be in `config.yaml`
# discussion/
- it's unclear what `deets` is and why that's not coming from upstream repos
- `upgrade-charm` hook should maybe provide a way to change nginx config too?
Thanks man... totally excited about getting this pimped-out version in the main charm! we need more like this.
Marco Ceppi (marcoceppi) wrote : Posted in a previous version of this proposal | # |
* Explicit values added (and config-changed updated to convert incoming values to lower case)
* Shared-fs relation removed, that will be added once Gluster charm is ready
* External repo added, currently defaults to github:
* All references to OMGUbuntu removed
* A backup charm would be a great idea, for now it's just not in the charm
* deets has been moved to _debug and is now a config option
* upgrade-charm now re-runs the hooks/config-
Mark Mims (mark-mims) wrote : | # |
awesome man... thanks!
debug is brilliant... we should perhaps add that as a "best practice" for charming... enable debug configs for the service itself if it supports it.
Mark Mims (mark-mims) wrote : | # |
marco, merge away.
Please watch out for the conflicts.
- 55. By Marco Ceppi
-
* Nginx as a webserver
* Allow for scale-out with nginx
* Track Themes, Plugins, and other custom files in remote repo
* Cache levels are user-definable
* Share files between nodes with NFS
* Lots of performance enhancements# Todo
* Add memcache support
* Wider support for remote files
Preview Diff
1 | === added file 'README.md' |
2 | --- README.md 1970-01-01 00:00:00 +0000 |
3 | +++ README.md 2012-08-21 13:22:29 +0000 |
4 | @@ -0,0 +1,152 @@ |
5 | +# Overview |
6 | + |
7 | +WordPress is a powerful blogging platform written in PHP. This charm aims to deploy WordPress in a fashion that will allow anyone to scale and grow out |
8 | +a single installation. |
9 | + |
10 | +# Installation |
11 | + |
12 | +This charm is available in the Juju Charm Store, to deploy you'll need at a minimum: a cloud environment, a working Juju installation, |
13 | +and a successful bootstrap. Please refer to the [Juju Getting Started](https://juju.ubuntu.com/docs/getting-started.html) documentation before continuing. |
14 | + |
15 | +Once bootstrapped, deploy the MySQL charm then this WordPress charm: |
16 | + |
17 | + juju deploy mysql |
18 | + juju deploy wordpress |
19 | + |
20 | +Add a relation between the two of them |
21 | + |
22 | + juju add-relation wordpress mysql |
23 | + |
24 | +Expose the WordPress installation |
25 | + |
26 | + juju expose wordpress |
27 | + |
28 | +# Configuration |
29 | + |
30 | +This WordPress charm comes with several tuning levels designed to encompass the different styles in which this charm will be used. |
31 | + |
32 | +## Tuning |
33 | + |
34 | +A use case for each tuning style is outlined below: |
35 | + |
36 | +### Bare |
37 | + |
38 | +The Bare configuration option is meant for those who wish to run the stock WordPress setup with no caching, no manipulation of data, |
39 | +and no additional scale out features enabled. This is ideal if you intend to install additional plugins to deal with coordinating |
40 | +WordPress units or simply wish to test drive WordPress as it is out of the box. This will still create a load-balancer when an additional |
41 | +unit is created, though everything else will be turned off (WordPress caching, APC OpCode caching, and NFS file sharing). |
42 | + |
43 | +To run this WordPress charm under a bare tuning level execute the following: |
44 | + |
45 | + juju set wordpress tuning=bare |
46 | + |
47 | +### Single |
48 | + |
49 | +When running in Single mode, this charm will make every attempt to provide a solid base for your WordPress install. By running in single |
50 | +the following will be enabled: Nginx microcache, APC OpCode caching, WordPress caching module, and the ability to sync files via NFS. |
51 | +While Single mode is designed to allow for scaling out, it's meant to only scale out for temporary relief; say in the event of a large |
52 | +traffic in-flux. It's recommended for long running scaled out versions that optimized is used. The removal of the file share speeds up |
53 | +the site and servers ensuring that the most efficient set up is provided. |
54 | + |
55 | +To run this WordPress charm under a single tuning level execute the following: |
56 | + |
57 | + juju set wordpress tuning=single |
58 | + |
59 | +### Optimized |
60 | + |
61 | +If you need to run WordPress on more than one instance constantly, or require scaling out and in on a regular basis, then Optimized is the |
62 | +recommended configuration. When you run WordPress under an Optimized tuning level, the ability to install, edit, and upgrade themes and plugins |
63 | +is disabled. By doing this the charm can drop the need for an NFS mount which is inefficient and serve everything from it's local disk. |
64 | +Everything else provided in Single level is available. In order to install or modify plugins with this setup you'll need to edit and commit |
65 | +them to a forked version of the charm in the files/wordpress/ directory. |
66 | + |
67 | +To run this WordPress charm under an optimized tuning level execute the following: |
68 | + |
69 | + juju set wordpress tuning=optimized |
70 | + |
71 | +## wp-content |
72 | + |
73 | +In order to allow for custom WordPress content within the Juju charm a separate configuration option exists for pointing to any Git or Bzr |
74 | +repository. An example of a valid formed wp-content repository can be found on the [Juju Tools Github page](https://github.com/jujutools/wordpress-site). |
75 | +To set the wp-content directive to a git repository, use one of the following formats making sure to replace items like `host`, `path`, and `repo` with their |
76 | +respective names: |
77 | + |
78 | + juju set wordpress wp-content=git@host:path/repo.git |
79 | + |
80 | +or |
81 | + |
82 | + juju set wordpress wp-content=http://host/path/repo.git |
83 | + |
84 | +or |
85 | + |
86 | + juju set wordpress wp-content=git://host/path/repo.git |
87 | + |
88 | +If you wish to use a bzr repository, then apply one of the following schemes replacing items like `host`, `username`, `path`, and `repo` with their respective values: |
89 | + |
90 | +For LaunchPad hosted repostiories: |
91 | + |
92 | + juju set wordpress wp-content=lp:~username/path/repo |
93 | + |
94 | +For other Bzr repositories: |
95 | + |
96 | + juju set wordpress wp-content=bzr://host/path/repo |
97 | + |
98 | +or |
99 | + |
100 | + juju set wordpress wp-content=bzr+ssh://host/path/repo |
101 | + |
102 | +Setting the wp-content option to an empty string ("") will result in no further updates being pulled from that repository; however, the last pull will remain |
103 | +on the system and will not be removed. |
104 | + |
105 | +## debug |
106 | + |
107 | +This option will create a directory `_debug` at the root of each unit (`http://unit-address/_debug`). In this directory are two scripts: info.php and apc.php. info.php |
108 | +is a simple phpinfo script that will outline exactly how the environment is configured. apc.php is the APC admin portal which provides APC caching details in addition |
109 | +to several administrative functions like clearing the APC cache. This should never be set to "yes" in production as it exposes detailed information about the environments |
110 | +and may provide a way for an intruder to DDoS the machine. |
111 | + |
112 | + juju set wordpress debug=yes |
113 | + |
114 | +to disable |
115 | + |
116 | + juju set wordpress debug=no |
117 | + |
118 | +The default is to have debugging disabled. |
119 | + |
120 | +# Caveats |
121 | + |
122 | +## Single mode and the scale-out |
123 | + |
124 | +If you're in Single mode and you want to/need to scale out, but you've been upgrading, modifying, and installing plugins + themes like |
125 | +a normal WordPress user on a normal install; you can still scale out but you'll need to deploy a shared-fs charm first. At the time of |
126 | +this writing only the NFS charm will work, but as more shared-fs charms come out (gluster, ceph, etc) that provide a shared-fs/mount |
127 | +interface those should all work as well. In this example we'll use NFS: |
128 | + |
129 | + juju deploy nfs |
130 | + juju add-relation nfs wordpress:nfs |
131 | + |
132 | +By doing so, everything in the wp-contents directory is moved to this NFS mount and then shared to all future WordPress units. It's strongly |
133 | +recommended that you first deploy the nfs mount, _then_ scale WordPress out. Failure to do so may result in data loss. Once nfs is deployed, |
134 | +running, and related you can scale out the WordPress unit using the following command: |
135 | + |
136 | + juju add-unit wordpress |
137 | + |
138 | +In the event you want more than one unit at a time (and do not wish to run the add-unit command multiple times) you can supply a `-n` number |
139 | +of units to add, so to add three more units: |
140 | + |
141 | + juju add-unit -n3 wordpress |
142 | + |
143 | +## I don't want to run three different machines for one WP install |
144 | + |
145 | +There is a "hack" that will allow you to deploy multiple full services to the same machine as the bootstrap node, this has nothing to do with |
146 | +the charm, but it's something that comes up more than once. Use this, of course, at your own risk. At any time the Juju developers may smart |
147 | +up and decide to remove this configuration option from the `environments.yaml` file. Prior to your first deployment you'll need to add the |
148 | +following line to your Juju Environments file: |
149 | + |
150 | + placement: local |
151 | + |
152 | +This will say "Everything that you deploy, will go on the bootstrap node". Make sure you plan to have a big enough bootstrap node to house |
153 | +both your database and WordPress install. After you've bootstrap'd the environment, deploy the MySQL and WordPress charms like you normally |
154 | +would. Instead of seeing three nodes you'll only see one, but both of your services will have been deployed. *FROM THIS POINT* you should |
155 | +either remove or comment out the `placement` line in the environments file. This will prevent issues from occurring when you try to deploy |
156 | +additional services or try to scale out existing services. |
157 | |
158 | === added file 'config.yaml' |
159 | --- config.yaml 1970-01-01 00:00:00 +0000 |
160 | +++ config.yaml 2012-08-21 13:22:29 +0000 |
161 | @@ -0,0 +1,26 @@ |
162 | +options: |
163 | + tuning: |
164 | + type: string |
165 | + default: "single" |
166 | + description: | |
167 | + This is the tuning level for the WordPress setup. There are three options: "bare", "single", and "optimized". |
168 | + "bare" will give you a nearly un-altered WordPress setup, as if you'd downloaded and set it up yourself. |
169 | + "single" will provide you with everything you need to run a singlular unit of WordPress. This doesn't take in to |
170 | + consideration that you'll be scaling at all. However, it will allow you to use WordPress free of any troubles and pesky |
171 | + limitations that typically happen during "optimized". While you _can_ scale out with this setting I encourage you read the README |
172 | + "optimized" will give you a hardened WordPress setup. Some of the features in the Admin panel will be locked down and theme edits/plugins |
173 | + can only be updated through he charm. This is the recommended setup for those who are in serious need of constant scaling. |
174 | + wp-content: |
175 | + type: string |
176 | + default: "https://github.com/jujutools/wordpress-site.git" |
177 | + description: | |
178 | + This is a full repository path to where the WordPress wp-contents can be found. At this time both Git and Bzr are |
179 | + supported. An example of what a wp-content repository should look like can be found at http://github.com/jujutools/wordpress-site. |
180 | + debug: |
181 | + type: string |
182 | + default: "no" |
183 | + description: | |
184 | + Setting this option to "yes" will expose /_debug on all instances over HTTP. In the _debug folder are two scripts, info.php and apc.php. |
185 | + info.php will display the phpinfo information for that server while the apc.php will provide APC cache stats (as well as additional administrative |
186 | + options for APC). |
187 | + |
188 | |
189 | === modified file 'copyright' |
190 | --- copyright 2011-06-10 11:20:27 +0000 |
191 | +++ copyright 2012-08-21 13:22:29 +0000 |
192 | @@ -1,7 +1,7 @@ |
193 | Format: http://dep.debian.net/deps/dep5/ |
194 | |
195 | Files: * |
196 | -Copyright: Copyright 2011, Canonical Ltd., All Rights Reserved. |
197 | +Copyright: Copyright 2012, Marco Ceppi, All Rights Reserved. |
198 | License: GPL-3 |
199 | This program is free software: you can redistribute it and/or modify |
200 | it under the terms of the GNU General Public License as published by |
201 | |
202 | === added directory 'files' |
203 | === added directory 'files/_debug' |
204 | === added file 'files/_debug/apc.php' |
205 | --- files/_debug/apc.php 1970-01-01 00:00:00 +0000 |
206 | +++ files/_debug/apc.php 2012-08-21 13:22:29 +0000 |
207 | @@ -0,0 +1,1364 @@ |
208 | +<?php |
209 | +/* |
210 | + +----------------------------------------------------------------------+ |
211 | + | APC | |
212 | + +----------------------------------------------------------------------+ |
213 | + | Copyright (c) 2006-2011 The PHP Group | |
214 | + +----------------------------------------------------------------------+ |
215 | + | This source file is subject to version 3.01 of the PHP license, | |
216 | + | that is bundled with this package in the file LICENSE, and is | |
217 | + | available through the world-wide-web at the following url: | |
218 | + | http://www.php.net/license/3_01.txt | |
219 | + | If you did not receive a copy of the PHP license and are unable to | |
220 | + | obtain it through the world-wide-web, please send a note to | |
221 | + | license@php.net so we can mail you a copy immediately. | |
222 | + +----------------------------------------------------------------------+ |
223 | + | Authors: Ralf Becker <beckerr@php.net> | |
224 | + | Rasmus Lerdorf <rasmus@php.net> | |
225 | + | Ilia Alshanetsky <ilia@prohost.org> | |
226 | + +----------------------------------------------------------------------+ |
227 | + |
228 | + All other licensing and usage conditions are those of the PHP Group. |
229 | + |
230 | +*/ |
231 | + |
232 | +$VERSION='$Id$'; |
233 | + |
234 | +////////// READ OPTIONAL CONFIGURATION FILE //////////// |
235 | +if (file_exists("apc.conf.php")) include("apc.conf.php"); |
236 | +//////////////////////////////////////////////////////// |
237 | + |
238 | +////////// BEGIN OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////// |
239 | + |
240 | +defaults('USE_AUTHENTICATION',0); // Use (internal) authentication - best choice if |
241 | + // no other authentication is available |
242 | + // If set to 0: |
243 | + // There will be no further authentication. You |
244 | + // will have to handle this by yourself! |
245 | + // If set to 1: |
246 | + // You need to change ADMIN_PASSWORD to make |
247 | + // this work! |
248 | +defaults('ADMIN_USERNAME',''); // Admin Username |
249 | +defaults('ADMIN_PASSWORD',''); // Admin Password - CHANGE THIS TO ENABLE!!! |
250 | + |
251 | +// (beckerr) I'm using a clear text password here, because I've no good idea how to let |
252 | +// users generate a md5 or crypt password in a easy way to fill it in above |
253 | + |
254 | +//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German |
255 | +defaults('DATE_FORMAT', ' m/d/Y h:i:s A'); // US |
256 | + |
257 | +defaults('GRAPH_SIZE',150); // Image size |
258 | + |
259 | +//defaults('PROXY', 'tcp://127.0.0.1:8080'); |
260 | + |
261 | +////////// END OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////// |
262 | + |
263 | + |
264 | +// "define if not defined" |
265 | +function defaults($d,$v) { |
266 | + if (!defined($d)) define($d,$v); // or just @define(...) |
267 | +} |
268 | + |
269 | +// rewrite $PHP_SELF to block XSS attacks |
270 | +// |
271 | +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : ''; |
272 | +$time = time(); |
273 | +$host = php_uname('n'); |
274 | +if($host) { $host = '('.$host.')'; } |
275 | +if (isset($_SERVER['SERVER_ADDR'])) { |
276 | + $host .= ' ('.$_SERVER['SERVER_ADDR'].')'; |
277 | +} |
278 | + |
279 | +// operation constants |
280 | +define('OB_HOST_STATS',1); |
281 | +define('OB_SYS_CACHE',2); |
282 | +define('OB_USER_CACHE',3); |
283 | +define('OB_SYS_CACHE_DIR',4); |
284 | +define('OB_VERSION_CHECK',9); |
285 | + |
286 | +// check validity of input variables |
287 | +$vardom=array( |
288 | + 'OB' => '/^\d+$/', // operational mode switch |
289 | + 'CC' => '/^[01]$/', // clear cache requested |
290 | + 'DU' => '/^.*$/', // Delete User Key |
291 | + 'SH' => '/^[a-z0-9]+$/', // shared object description |
292 | + |
293 | + 'IMG' => '/^[123]$/', // image to generate |
294 | + 'LO' => '/^1$/', // login requested |
295 | + |
296 | + 'COUNT' => '/^\d+$/', // number of line displayed in list |
297 | + 'SCOPE' => '/^[AD]$/', // list view scope |
298 | + 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key |
299 | + 'SORT2' => '/^[DA]$/', // second sort key |
300 | + 'AGGR' => '/^\d+$/', // aggregation by dir level |
301 | + 'SEARCH' => '~^[a-zA-Z0-1/_.-]*$~' // aggregation by dir level |
302 | +); |
303 | + |
304 | +// default cache mode |
305 | +$cache_mode='opcode'; |
306 | + |
307 | +// cache scope |
308 | +$scope_list=array( |
309 | + 'A' => 'cache_list', |
310 | + 'D' => 'deleted_list' |
311 | +); |
312 | + |
313 | +// handle POST and GET requests |
314 | +if (empty($_REQUEST)) { |
315 | + if (!empty($_GET) && !empty($_POST)) { |
316 | + $_REQUEST = array_merge($_GET, $_POST); |
317 | + } else if (!empty($_GET)) { |
318 | + $_REQUEST = $_GET; |
319 | + } else if (!empty($_POST)) { |
320 | + $_REQUEST = $_POST; |
321 | + } else { |
322 | + $_REQUEST = array(); |
323 | + } |
324 | +} |
325 | + |
326 | +// check parameter syntax |
327 | +foreach($vardom as $var => $dom) { |
328 | + if (!isset($_REQUEST[$var])) { |
329 | + $MYREQUEST[$var]=NULL; |
330 | + } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) { |
331 | + $MYREQUEST[$var]=$_REQUEST[$var]; |
332 | + } else { |
333 | + $MYREQUEST[$var]=$_REQUEST[$var]=NULL; |
334 | + } |
335 | +} |
336 | + |
337 | +// check parameter sematics |
338 | +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A"; |
339 | +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H"; |
340 | +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D"; |
341 | +if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS; |
342 | +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20; |
343 | +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A'; |
344 | + |
345 | +$MY_SELF= |
346 | + "$PHP_SELF". |
347 | + "?SCOPE=".$MYREQUEST['SCOPE']. |
348 | + "&SORT1=".$MYREQUEST['SORT1']. |
349 | + "&SORT2=".$MYREQUEST['SORT2']. |
350 | + "&COUNT=".$MYREQUEST['COUNT']; |
351 | +$MY_SELF_WO_SORT= |
352 | + "$PHP_SELF". |
353 | + "?SCOPE=".$MYREQUEST['SCOPE']. |
354 | + "&COUNT=".$MYREQUEST['COUNT']; |
355 | + |
356 | +// authentication needed? |
357 | +// |
358 | +if (!USE_AUTHENTICATION) { |
359 | + $AUTHENTICATED=1; |
360 | +} else { |
361 | + $AUTHENTICATED=0; |
362 | + if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) { |
363 | + |
364 | + if (!isset($_SERVER['PHP_AUTH_USER']) || |
365 | + !isset($_SERVER['PHP_AUTH_PW']) || |
366 | + $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME || |
367 | + $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) { |
368 | + Header("WWW-Authenticate: Basic realm=\"APC Login\""); |
369 | + Header("HTTP/1.0 401 Unauthorized"); |
370 | + |
371 | + echo <<<EOB |
372 | + <html><body> |
373 | + <h1>Rejected!</h1> |
374 | + <big>Wrong Username or Password!</big><br/> <br/> |
375 | + <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big> |
376 | + </body></html> |
377 | +EOB; |
378 | + exit; |
379 | + |
380 | + } else { |
381 | + $AUTHENTICATED=1; |
382 | + } |
383 | + } |
384 | +} |
385 | + |
386 | +// select cache mode |
387 | +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) { |
388 | + $cache_mode='user'; |
389 | +} |
390 | +// clear cache |
391 | +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) { |
392 | + apc_clear_cache($cache_mode); |
393 | +} |
394 | + |
395 | +if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) { |
396 | + apc_delete($MYREQUEST['DU']); |
397 | +} |
398 | + |
399 | +if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) { |
400 | + echo "No cache info available. APC does not appear to be running."; |
401 | + exit; |
402 | +} |
403 | + |
404 | +$cache_user = apc_cache_info('user', 1); |
405 | +$mem=apc_sma_info(); |
406 | +if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; } // Avoid division by 0 errors on a cache clear |
407 | + |
408 | +// don't cache this page |
409 | +// |
410 | +header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 |
411 | +header("Cache-Control: post-check=0, pre-check=0", false); |
412 | +header("Pragma: no-cache"); // HTTP/1.0 |
413 | + |
414 | +function duration($ts) { |
415 | + global $time; |
416 | + $years = (int)((($time - $ts)/(7*86400))/52.177457); |
417 | + $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400)); |
418 | + $weeks = (int)(($rem)/(7*86400)); |
419 | + $days = (int)(($rem)/86400) - $weeks*7; |
420 | + $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24; |
421 | + $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60; |
422 | + $str = ''; |
423 | + if($years==1) $str .= "$years year, "; |
424 | + if($years>1) $str .= "$years years, "; |
425 | + if($weeks==1) $str .= "$weeks week, "; |
426 | + if($weeks>1) $str .= "$weeks weeks, "; |
427 | + if($days==1) $str .= "$days day,"; |
428 | + if($days>1) $str .= "$days days,"; |
429 | + if($hours == 1) $str .= " $hours hour and"; |
430 | + if($hours>1) $str .= " $hours hours and"; |
431 | + if($mins == 1) $str .= " 1 minute"; |
432 | + else $str .= " $mins minutes"; |
433 | + return $str; |
434 | +} |
435 | + |
436 | +// create graphics |
437 | +// |
438 | +function graphics_avail() { |
439 | + return extension_loaded('gd'); |
440 | +} |
441 | +if (isset($MYREQUEST['IMG'])) |
442 | +{ |
443 | + if (!graphics_avail()) { |
444 | + exit(0); |
445 | + } |
446 | + |
447 | + function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) { |
448 | + $r=$diameter/2; |
449 | + $w=deg2rad((360+$start+($end-$start)/2)%360); |
450 | + |
451 | + |
452 | + if (function_exists("imagefilledarc")) { |
453 | + // exists only if GD 2.0.1 is avaliable |
454 | + imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE); |
455 | + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE); |
456 | + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); |
457 | + } else { |
458 | + imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2); |
459 | + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); |
460 | + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); |
461 | + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); |
462 | + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); |
463 | + imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2); |
464 | + } |
465 | + if ($text) { |
466 | + if ($placeindex>0) { |
467 | + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); |
468 | + imagestring($im,4,$diameter, $placeindex*12,$text,$color1); |
469 | + |
470 | + } else { |
471 | + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); |
472 | + } |
473 | + } |
474 | + } |
475 | + |
476 | + function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) { |
477 | + $r=$diameter/2; |
478 | + $w=deg2rad((360+$start+($end-$start)/2)%360); |
479 | + |
480 | + if ($placeindex>0) { |
481 | + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); |
482 | + imagestring($im,4,$diameter, $placeindex*12,$text,$color1); |
483 | + |
484 | + } else { |
485 | + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); |
486 | + } |
487 | + } |
488 | + |
489 | + function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') { |
490 | + global $col_black; |
491 | + $x1=$x+$w-1; |
492 | + $y1=$y+$h-1; |
493 | + |
494 | + imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black); |
495 | + if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2); |
496 | + else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2); |
497 | + imagerectangle($im, $x, $y1, $x1, $y, $color1); |
498 | + if ($text) { |
499 | + if ($placeindex>0) { |
500 | + |
501 | + if ($placeindex<16) |
502 | + { |
503 | + $px=5; |
504 | + $py=$placeindex*12+6; |
505 | + imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2); |
506 | + imageline($im,$x,$y+$h/2,$px+90,$py,$color2); |
507 | + imagestring($im,2,$px,$py-6,$text,$color1); |
508 | + |
509 | + } else { |
510 | + if ($placeindex<31) { |
511 | + $px=$x+40*2; |
512 | + $py=($placeindex-15)*12+6; |
513 | + } else { |
514 | + $px=$x+40*2+100*intval(($placeindex-15)/15); |
515 | + $py=($placeindex%15)*12+6; |
516 | + } |
517 | + imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2); |
518 | + imageline($im,$x+$w,$y+$h/2,$px,$py,$color2); |
519 | + imagestring($im,2,$px+2,$py-6,$text,$color1); |
520 | + } |
521 | + } else { |
522 | + imagestring($im,4,$x+5,$y1-16,$text,$color1); |
523 | + } |
524 | + } |
525 | + } |
526 | + |
527 | + |
528 | + $size = GRAPH_SIZE; // image size |
529 | + if ($MYREQUEST['IMG']==3) |
530 | + $image = imagecreate(2*$size+150, $size+10); |
531 | + else |
532 | + $image = imagecreate($size+50, $size+10); |
533 | + |
534 | + $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); |
535 | + $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30); |
536 | + $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60); |
537 | + $col_black = imagecolorallocate($image, 0, 0, 0); |
538 | + imagecolortransparent($image,$col_white); |
539 | + |
540 | + switch ($MYREQUEST['IMG']) { |
541 | + |
542 | + case 1: |
543 | + $s=$mem['num_seg']*$mem['seg_size']; |
544 | + $a=$mem['avail_mem']; |
545 | + $x=$y=$size/2; |
546 | + $fuzz = 0.000001; |
547 | + |
548 | + // This block of code creates the pie chart. It is a lot more complex than you |
549 | + // would expect because we try to visualize any memory fragmentation as well. |
550 | + $angle_from = 0; |
551 | + $string_placement=array(); |
552 | + for($i=0; $i<$mem['num_seg']; $i++) { |
553 | + $ptr = 0; |
554 | + $free = $mem['block_lists'][$i]; |
555 | + uasort($free, 'block_sort'); |
556 | + foreach($free as $block) { |
557 | + if($block['offset']!=$ptr) { // Used block |
558 | + $angle_to = $angle_from+($block['offset']-$ptr)/$s; |
559 | + if(($angle_to+$fuzz)>1) $angle_to = 1; |
560 | + if( ($angle_to*360) - ($angle_from*360) >= 1) { |
561 | + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red); |
562 | + if (($angle_to-$angle_from)>0.05) { |
563 | + array_push($string_placement, array($angle_from,$angle_to)); |
564 | + } |
565 | + } |
566 | + $angle_from = $angle_to; |
567 | + } |
568 | + $angle_to = $angle_from+($block['size'])/$s; |
569 | + if(($angle_to+$fuzz)>1) $angle_to = 1; |
570 | + if( ($angle_to*360) - ($angle_from*360) >= 1) { |
571 | + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green); |
572 | + if (($angle_to-$angle_from)>0.05) { |
573 | + array_push($string_placement, array($angle_from,$angle_to)); |
574 | + } |
575 | + } |
576 | + $angle_from = $angle_to; |
577 | + $ptr = $block['offset']+$block['size']; |
578 | + } |
579 | + if ($ptr < $mem['seg_size']) { // memory at the end |
580 | + $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s; |
581 | + if(($angle_to+$fuzz)>1) $angle_to = 1; |
582 | + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red); |
583 | + if (($angle_to-$angle_from)>0.05) { |
584 | + array_push($string_placement, array($angle_from,$angle_to)); |
585 | + } |
586 | + } |
587 | + } |
588 | + foreach ($string_placement as $angle) { |
589 | + text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0]))); |
590 | + } |
591 | + break; |
592 | + |
593 | + case 2: |
594 | + $s=$cache['num_hits']+$cache['num_misses']; |
595 | + $a=$cache['num_hits']; |
596 | + |
597 | + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s)); |
598 | + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s)); |
599 | + break; |
600 | + |
601 | + case 3: |
602 | + $s=$mem['num_seg']*$mem['seg_size']; |
603 | + $a=$mem['avail_mem']; |
604 | + $x=130; |
605 | + $y=1; |
606 | + $j=1; |
607 | + |
608 | + // This block of code creates the bar chart. It is a lot more complex than you |
609 | + // would expect because we try to visualize any memory fragmentation as well. |
610 | + for($i=0; $i<$mem['num_seg']; $i++) { |
611 | + $ptr = 0; |
612 | + $free = $mem['block_lists'][$i]; |
613 | + uasort($free, 'block_sort'); |
614 | + foreach($free as $block) { |
615 | + if($block['offset']!=$ptr) { // Used block |
616 | + $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s; |
617 | + if ($h>0) { |
618 | + $j++; |
619 | + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j); |
620 | + else fill_box($image,$x,$y,50,$h,$col_black,$col_red); |
621 | + } |
622 | + $y+=$h; |
623 | + } |
624 | + $h=(GRAPH_SIZE-5)*($block['size'])/$s; |
625 | + if ($h>0) { |
626 | + $j++; |
627 | + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j); |
628 | + else fill_box($image,$x,$y,50,$h,$col_black,$col_green); |
629 | + } |
630 | + $y+=$h; |
631 | + $ptr = $block['offset']+$block['size']; |
632 | + } |
633 | + if ($ptr < $mem['seg_size']) { // memory at the end |
634 | + $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s; |
635 | + if ($h > 0) { |
636 | + fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++); |
637 | + } |
638 | + } |
639 | + } |
640 | + break; |
641 | + case 4: |
642 | + $s=$cache['num_hits']+$cache['num_misses']; |
643 | + $a=$cache['num_hits']; |
644 | + |
645 | + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s)); |
646 | + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s)); |
647 | + break; |
648 | + |
649 | + } |
650 | + header("Content-type: image/png"); |
651 | + imagepng($image); |
652 | + exit; |
653 | +} |
654 | + |
655 | +// pretty printer for byte values |
656 | +// |
657 | +function bsize($s) { |
658 | + foreach (array('','K','M','G') as $i => $k) { |
659 | + if ($s < 1024) break; |
660 | + $s/=1024; |
661 | + } |
662 | + return sprintf("%5.1f %sBytes",$s,$k); |
663 | +} |
664 | + |
665 | +// sortable table header in "scripts for this host" view |
666 | +function sortheader($key,$name,$extra='') { |
667 | + global $MYREQUEST, $MY_SELF_WO_SORT; |
668 | + |
669 | + if ($MYREQUEST['SORT1']==$key) { |
670 | + $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A'; |
671 | + } |
672 | + return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>"; |
673 | + |
674 | +} |
675 | + |
676 | +// create menu entry |
677 | +function menu_entry($ob,$title) { |
678 | + global $MYREQUEST,$MY_SELF; |
679 | + if ($MYREQUEST['OB']!=$ob) { |
680 | + return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>"; |
681 | + } else if (empty($MYREQUEST['SH'])) { |
682 | + return "<li><span class=active>$title</span></li>"; |
683 | + } else { |
684 | + return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>"; |
685 | + } |
686 | +} |
687 | + |
688 | +function put_login_link($s="Login") |
689 | +{ |
690 | + global $MY_SELF,$MYREQUEST,$AUTHENTICATED; |
691 | + // needs ADMIN_PASSWORD to be changed! |
692 | + // |
693 | + if (!USE_AUTHENTICATION) { |
694 | + return; |
695 | + } else if (ADMIN_PASSWORD=='password') |
696 | + { |
697 | + print <<<EOB |
698 | + <a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a> |
699 | +EOB; |
700 | + } else if ($AUTHENTICATED) { |
701 | + print <<<EOB |
702 | + '{$_SERVER['PHP_AUTH_USER']}' logged in! |
703 | +EOB; |
704 | + } else{ |
705 | + print <<<EOB |
706 | + <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a> |
707 | +EOB; |
708 | + } |
709 | +} |
710 | + |
711 | +function block_sort($array1, $array2) |
712 | +{ |
713 | + if ($array1['offset'] > $array2['offset']) { |
714 | + return 1; |
715 | + } else { |
716 | + return -1; |
717 | + } |
718 | +} |
719 | + |
720 | + |
721 | +?> |
722 | +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
723 | +<html> |
724 | +<head><title>APC INFO <?php echo $host ?></title> |
725 | +<style><!-- |
726 | +body { background:white; font-size:100.01%; margin:0; padding:0; } |
727 | +body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; } |
728 | +* html body {font-size:0.8em} |
729 | +* html p {font-size:0.8em} |
730 | +* html td {font-size:0.8em} |
731 | +* html th {font-size:0.8em} |
732 | +* html input {font-size:0.8em} |
733 | +* html submit {font-size:0.8em} |
734 | +td { vertical-align:top } |
735 | +a { color:black; font-weight:none; text-decoration:none; } |
736 | +a:hover { text-decoration:underline; } |
737 | +div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; } |
738 | + |
739 | + |
740 | +div.head div.login { |
741 | + position:absolute; |
742 | + right: 1em; |
743 | + top: 1.2em; |
744 | + color:white; |
745 | + width:6em; |
746 | + } |
747 | +div.head div.login a { |
748 | + position:absolute; |
749 | + right: 0em; |
750 | + background:rgb(119,123,180); |
751 | + border:solid rgb(102,102,153) 2px; |
752 | + color:white; |
753 | + font-weight:bold; |
754 | + padding:0.1em 0.5em 0.1em 0.5em; |
755 | + text-decoration:none; |
756 | + } |
757 | +div.head div.login a:hover { |
758 | + background:rgb(193,193,244); |
759 | + } |
760 | + |
761 | +h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; } |
762 | +* html h1.apc { margin-bottom:-7px; } |
763 | +h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); } |
764 | +h1.apc div.logo span.logo { |
765 | + background:rgb(119,123,180); |
766 | + color:black; |
767 | + border-right: solid black 1px; |
768 | + border-bottom: solid black 1px; |
769 | + font-style:italic; |
770 | + font-size:1em; |
771 | + padding-left:1.2em; |
772 | + padding-right:1.2em; |
773 | + text-align:right; |
774 | + } |
775 | +h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; } |
776 | +h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; } |
777 | +h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; } |
778 | +hr.apc { |
779 | + background:white; |
780 | + border-bottom:solid rgb(102,102,153) 1px; |
781 | + border-style:none; |
782 | + border-top:solid rgb(102,102,153) 10px; |
783 | + height:12px; |
784 | + margin:0; |
785 | + margin-top:1px; |
786 | + padding:0; |
787 | +} |
788 | + |
789 | +ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;} |
790 | +ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%} |
791 | +ol.menu a { |
792 | + background:rgb(153,153,204); |
793 | + border:solid rgb(102,102,153) 2px; |
794 | + color:white; |
795 | + font-weight:bold; |
796 | + margin-right:0em; |
797 | + padding:0.1em 0.5em 0.1em 0.5em; |
798 | + text-decoration:none; |
799 | + margin-left: 5px; |
800 | + } |
801 | +ol.menu a.child_active { |
802 | + background:rgb(153,153,204); |
803 | + border:solid rgb(102,102,153) 2px; |
804 | + color:white; |
805 | + font-weight:bold; |
806 | + margin-right:0em; |
807 | + padding:0.1em 0.5em 0.1em 0.5em; |
808 | + text-decoration:none; |
809 | + border-left: solid black 5px; |
810 | + margin-left: 0px; |
811 | + } |
812 | +ol.menu span.active { |
813 | + background:rgb(153,153,204); |
814 | + border:solid rgb(102,102,153) 2px; |
815 | + color:black; |
816 | + font-weight:bold; |
817 | + margin-right:0em; |
818 | + padding:0.1em 0.5em 0.1em 0.5em; |
819 | + text-decoration:none; |
820 | + border-left: solid black 5px; |
821 | + } |
822 | +ol.menu span.inactive { |
823 | + background:rgb(193,193,244); |
824 | + border:solid rgb(182,182,233) 2px; |
825 | + color:white; |
826 | + font-weight:bold; |
827 | + margin-right:0em; |
828 | + padding:0.1em 0.5em 0.1em 0.5em; |
829 | + text-decoration:none; |
830 | + margin-left: 5px; |
831 | + } |
832 | +ol.menu a:hover { |
833 | + background:rgb(193,193,244); |
834 | + text-decoration:none; |
835 | + } |
836 | + |
837 | + |
838 | +div.info { |
839 | + background:rgb(204,204,204); |
840 | + border:solid rgb(204,204,204) 1px; |
841 | + margin-bottom:1em; |
842 | + } |
843 | +div.info h2 { |
844 | + background:rgb(204,204,204); |
845 | + color:black; |
846 | + font-size:1em; |
847 | + margin:0; |
848 | + padding:0.1em 1em 0.1em 1em; |
849 | + } |
850 | +div.info table { |
851 | + border:solid rgb(204,204,204) 1px; |
852 | + border-spacing:0; |
853 | + width:100%; |
854 | + } |
855 | +div.info table th { |
856 | + background:rgb(204,204,204); |
857 | + color:white; |
858 | + margin:0; |
859 | + padding:0.1em 1em 0.1em 1em; |
860 | + } |
861 | +div.info table th a.sortable { color:black; } |
862 | +div.info table tr.tr-0 { background:rgb(238,238,238); } |
863 | +div.info table tr.tr-1 { background:rgb(221,221,221); } |
864 | +div.info table td { padding:0.3em 1em 0.3em 1em; } |
865 | +div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; } |
866 | +div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; } |
867 | +div.info table td h3 { |
868 | + color:black; |
869 | + font-size:1.1em; |
870 | + margin-left:-0.3em; |
871 | + } |
872 | + |
873 | +div.graph { margin-bottom:1em } |
874 | +div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; } |
875 | +div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; } |
876 | +div.graph table td.td-0 { background:rgb(238,238,238); } |
877 | +div.graph table td.td-1 { background:rgb(221,221,221); } |
878 | +div.graph table td { padding:0.2em 1em 0.4em 1em; } |
879 | + |
880 | +div.div1,div.div2 { margin-bottom:1em; width:35em; } |
881 | +div.div3 { position:absolute; left:40em; top:1em; width:580px; } |
882 | +//div.div3 { position:absolute; left:37em; top:1em; right:1em; } |
883 | + |
884 | +div.sorting { margin:1.5em 0em 1.5em 2em } |
885 | +.center { text-align:center } |
886 | +.aright { position:absolute;right:1em } |
887 | +.right { text-align:right } |
888 | +.ok { color:rgb(0,200,0); font-weight:bold} |
889 | +.failed { color:rgb(200,0,0); font-weight:bold} |
890 | + |
891 | +span.box { |
892 | + border: black solid 1px; |
893 | + border-right:solid black 2px; |
894 | + border-bottom:solid black 2px; |
895 | + padding:0 0.5em 0 0.5em; |
896 | + margin-right:1em; |
897 | +} |
898 | +span.green { background:#60F060; padding:0 0.5em 0 0.5em} |
899 | +span.red { background:#D06030; padding:0 0.5em 0 0.5em } |
900 | + |
901 | +div.authneeded { |
902 | + background:rgb(238,238,238); |
903 | + border:solid rgb(204,204,204) 1px; |
904 | + color:rgb(200,0,0); |
905 | + font-size:1.2em; |
906 | + font-weight:bold; |
907 | + padding:2em; |
908 | + text-align:center; |
909 | + } |
910 | + |
911 | +input { |
912 | + background:rgb(153,153,204); |
913 | + border:solid rgb(102,102,153) 2px; |
914 | + color:white; |
915 | + font-weight:bold; |
916 | + margin-right:1em; |
917 | + padding:0.1em 0.5em 0.1em 0.5em; |
918 | + } |
919 | +//--> |
920 | +</style> |
921 | +</head> |
922 | +<body> |
923 | +<div class="head"> |
924 | + <h1 class="apc"> |
925 | + <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div> |
926 | + <div class="nameinfo">Opcode Cache</div> |
927 | + </h1> |
928 | + <div class="login"> |
929 | + <?php put_login_link(); ?> |
930 | + </div> |
931 | + <hr class="apc"> |
932 | +</div> |
933 | +<?php |
934 | + |
935 | + |
936 | +// Display main Menu |
937 | +echo <<<EOB |
938 | + <ol class=menu> |
939 | + <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li> |
940 | +EOB; |
941 | +echo |
942 | + menu_entry(1,'View Host Stats'), |
943 | + menu_entry(2,'System Cache Entries'); |
944 | +if ($AUTHENTICATED) { |
945 | + echo menu_entry(4,'Per-Directory Entries'); |
946 | +} |
947 | +echo |
948 | + menu_entry(3,'User Cache Entries'), |
949 | + menu_entry(9,'Version Check'); |
950 | + |
951 | +if ($AUTHENTICATED) { |
952 | + echo <<<EOB |
953 | + <li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascript:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li> |
954 | +EOB; |
955 | +} |
956 | +echo <<<EOB |
957 | + </ol> |
958 | +EOB; |
959 | + |
960 | + |
961 | +// CONTENT |
962 | +echo <<<EOB |
963 | + <div class=content> |
964 | +EOB; |
965 | + |
966 | +// MAIN SWITCH STATEMENT |
967 | + |
968 | +switch ($MYREQUEST['OB']) { |
969 | + |
970 | + |
971 | + |
972 | + |
973 | + |
974 | +// ----------------------------------------------- |
975 | +// Host Stats |
976 | +// ----------------------------------------------- |
977 | +case OB_HOST_STATS: |
978 | + $mem_size = $mem['num_seg']*$mem['seg_size']; |
979 | + $mem_avail= $mem['avail_mem']; |
980 | + $mem_used = $mem_size-$mem_avail; |
981 | + $seg_size = bsize($mem['seg_size']); |
982 | + $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time'])); |
983 | + $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time'])); |
984 | + $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time'])); |
985 | + $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time'])); |
986 | + $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time'])); |
987 | + $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time'])); |
988 | + $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time'])); |
989 | + $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time'])); |
990 | + $apcversion = phpversion('apc'); |
991 | + $phpversion = phpversion(); |
992 | + $number_files = $cache['num_entries']; |
993 | + $size_files = bsize($cache['mem_size']); |
994 | + $number_vars = $cache_user['num_entries']; |
995 | + $size_vars = bsize($cache_user['mem_size']); |
996 | + $i=0; |
997 | + echo <<< EOB |
998 | + <div class="info div1"><h2>General Cache Information</h2> |
999 | + <table cellspacing=0><tbody> |
1000 | + <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr> |
1001 | + <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr> |
1002 | +EOB; |
1003 | + |
1004 | + if(!empty($_SERVER['SERVER_NAME'])) |
1005 | + echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n"; |
1006 | + if(!empty($_SERVER['SERVER_SOFTWARE'])) |
1007 | + echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n"; |
1008 | + |
1009 | + echo <<<EOB |
1010 | + <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size |
1011 | + <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking) |
1012 | + </td></tr> |
1013 | +EOB; |
1014 | + echo '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>'; |
1015 | + echo '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>'; |
1016 | + echo '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>'; |
1017 | + echo <<<EOB |
1018 | + </tbody></table> |
1019 | + </div> |
1020 | + |
1021 | + <div class="info div1"><h2>File Cache Information</h2> |
1022 | + <table cellspacing=0><tbody> |
1023 | + <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr> |
1024 | + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr> |
1025 | + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr> |
1026 | + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr> |
1027 | + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr> |
1028 | + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr> |
1029 | + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr> |
1030 | + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr> |
1031 | + </tbody></table> |
1032 | + </div> |
1033 | + |
1034 | + <div class="info div1"><h2>User Cache Information</h2> |
1035 | + <table cellspacing=0><tbody> |
1036 | + <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr> |
1037 | + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr> |
1038 | + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr> |
1039 | + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr> |
1040 | + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr> |
1041 | + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr> |
1042 | + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr> |
1043 | + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr> |
1044 | + |
1045 | + </tbody></table> |
1046 | + </div> |
1047 | + |
1048 | + <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody> |
1049 | +EOB; |
1050 | + |
1051 | + $j = 0; |
1052 | + foreach (ini_get_all('apc') as $k => $v) { |
1053 | + echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n"; |
1054 | + $j = 1 - $j; |
1055 | + } |
1056 | + |
1057 | + if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1) |
1058 | + $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>"; |
1059 | + else |
1060 | + $mem_note = "Memory Usage"; |
1061 | + |
1062 | + echo <<< EOB |
1063 | + </tbody></table> |
1064 | + </div> |
1065 | + |
1066 | + <div class="graph div3"><h2>Host Status Diagrams</h2> |
1067 | + <table cellspacing=0><tbody> |
1068 | +EOB; |
1069 | + $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10); |
1070 | + echo <<<EOB |
1071 | + <tr> |
1072 | + <td class=td-0>$mem_note</td> |
1073 | + <td class=td-1>Hits & Misses</td> |
1074 | + </tr> |
1075 | +EOB; |
1076 | + |
1077 | + echo |
1078 | + graphics_avail() ? |
1079 | + '<tr>'. |
1080 | + "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>". |
1081 | + "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n" |
1082 | + : "", |
1083 | + '<tr>', |
1084 | + '<td class=td-0><span class="green box"> </span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n", |
1085 | + '<td class=td-1><span class="green box"> </span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n", |
1086 | + '</tr>', |
1087 | + '<tr>', |
1088 | + '<td class=td-0><span class="red box"> </span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n", |
1089 | + '<td class=td-1><span class="red box"> </span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n"; |
1090 | + echo <<< EOB |
1091 | + </tr> |
1092 | + </tbody></table> |
1093 | + |
1094 | + <br/> |
1095 | + <h2>Detailed Memory Usage and Fragmentation</h2> |
1096 | + <table cellspacing=0><tbody> |
1097 | + <tr> |
1098 | + <td class=td-0 colspan=2><br/> |
1099 | +EOB; |
1100 | + |
1101 | + // Fragementation: (freeseg - 1) / total_seg |
1102 | + $nseg = $freeseg = $fragsize = $freetotal = 0; |
1103 | + for($i=0; $i<$mem['num_seg']; $i++) { |
1104 | + $ptr = 0; |
1105 | + foreach($mem['block_lists'][$i] as $block) { |
1106 | + if ($block['offset'] != $ptr) { |
1107 | + ++$nseg; |
1108 | + } |
1109 | + $ptr = $block['offset'] + $block['size']; |
1110 | + /* Only consider blocks <5M for the fragmentation % */ |
1111 | + if($block['size']<(5*1024*1024)) $fragsize+=$block['size']; |
1112 | + $freetotal+=$block['size']; |
1113 | + } |
1114 | + $freeseg += count($mem['block_lists'][$i]); |
1115 | + } |
1116 | + |
1117 | + if ($freeseg > 1) { |
1118 | + $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg); |
1119 | + } else { |
1120 | + $frag = "0%"; |
1121 | + } |
1122 | + |
1123 | + if (graphics_avail()) { |
1124 | + $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10); |
1125 | + echo <<<EOB |
1126 | + <img alt="" $size src="$PHP_SELF?IMG=3&$time"> |
1127 | +EOB; |
1128 | + } |
1129 | + echo <<<EOB |
1130 | + </br>Fragmentation: $frag |
1131 | + </td> |
1132 | + </tr> |
1133 | +EOB; |
1134 | + if(isset($mem['adist'])) { |
1135 | + foreach($mem['adist'] as $i=>$v) { |
1136 | + $cur = pow(2,$i); $nxt = pow(2,$i+1)-1; |
1137 | + if($i==0) $range = "1"; |
1138 | + else $range = "$cur - $nxt"; |
1139 | + echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n"; |
1140 | + } |
1141 | + } |
1142 | + echo <<<EOB |
1143 | + </tbody></table> |
1144 | + </div> |
1145 | +EOB; |
1146 | + |
1147 | + break; |
1148 | + |
1149 | + |
1150 | +// ----------------------------------------------- |
1151 | +// User Cache Entries |
1152 | +// ----------------------------------------------- |
1153 | +case OB_USER_CACHE: |
1154 | + if (!$AUTHENTICATED) { |
1155 | + echo '<div class="error">You need to login to see the user values here!<br/> <br/>'; |
1156 | + put_login_link("Login now!"); |
1157 | + echo '</div>'; |
1158 | + break; |
1159 | + } |
1160 | + $fieldname='info'; |
1161 | + $fieldheading='User Entry Label'; |
1162 | + $fieldkey='info'; |
1163 | + |
1164 | +// ----------------------------------------------- |
1165 | +// System Cache Entries |
1166 | +// ----------------------------------------------- |
1167 | +case OB_SYS_CACHE: |
1168 | + if (!isset($fieldname)) |
1169 | + { |
1170 | + $fieldname='filename'; |
1171 | + $fieldheading='Script Filename'; |
1172 | + if(ini_get("apc.stat")) $fieldkey='inode'; |
1173 | + else $fieldkey='filename'; |
1174 | + } |
1175 | + if (!empty($MYREQUEST['SH'])) |
1176 | + { |
1177 | + echo <<< EOB |
1178 | + <div class="info"><table cellspacing=0><tbody> |
1179 | + <tr><th>Attribute</th><th>Value</th></tr> |
1180 | +EOB; |
1181 | + |
1182 | + $m=0; |
1183 | + foreach($scope_list as $j => $list) { |
1184 | + foreach($cache[$list] as $i => $entry) { |
1185 | + if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue; |
1186 | + foreach($entry as $k => $value) { |
1187 | + if (!$AUTHENTICATED) { |
1188 | + // hide all path entries if not logged in |
1189 | + $value=preg_replace('/^.*(\\/|\\\\)/','<i><hidden></i>/',$value); |
1190 | + } |
1191 | + |
1192 | + if ($k == "num_hits") { |
1193 | + $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']); |
1194 | + } |
1195 | + if ($k == 'deletion_time') { |
1196 | + if(!$entry['deletion_time']) $value = "None"; |
1197 | + } |
1198 | + echo |
1199 | + "<tr class=tr-$m>", |
1200 | + "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>", |
1201 | + "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8'),"</td>", |
1202 | + "</tr>"; |
1203 | + $m=1-$m; |
1204 | + } |
1205 | + if($fieldkey=='info') { |
1206 | + echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>"; |
1207 | + $output = var_export(apc_fetch($entry[$fieldkey]),true); |
1208 | + echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8'); |
1209 | + echo "</pre></td></tr>\n"; |
1210 | + } |
1211 | + break; |
1212 | + } |
1213 | + } |
1214 | + |
1215 | + echo <<<EOB |
1216 | + </tbody></table> |
1217 | + </div> |
1218 | +EOB; |
1219 | + break; |
1220 | + } |
1221 | + |
1222 | + $cols=6; |
1223 | + echo <<<EOB |
1224 | + <div class=sorting><form>Scope: |
1225 | + <input type=hidden name=OB value={$MYREQUEST['OB']}> |
1226 | + <select name=SCOPE> |
1227 | +EOB; |
1228 | + echo |
1229 | + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>", |
1230 | + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>", |
1231 | + "</select>", |
1232 | + ", Sorting:<select name=SORT1>", |
1233 | + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>", |
1234 | + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>", |
1235 | + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>", |
1236 | + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>", |
1237 | + "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>", |
1238 | + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>", |
1239 | + "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>"; |
1240 | + if($fieldname=='info') echo |
1241 | + "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>"; |
1242 | + echo |
1243 | + '</select>', |
1244 | + '<select name=SORT2>', |
1245 | + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>', |
1246 | + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>', |
1247 | + '</select>', |
1248 | + '<select name=COUNT onChange="form.submit()">', |
1249 | + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>', |
1250 | + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>', |
1251 | + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>', |
1252 | + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>', |
1253 | + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>', |
1254 | + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>', |
1255 | + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>', |
1256 | + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>', |
1257 | + '</select>', |
1258 | + ' Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>', |
1259 | + ' <input type=submit value="GO!">', |
1260 | + '</form></div>'; |
1261 | + |
1262 | + if (isset($MYREQUEST['SEARCH'])) { |
1263 | + // Don't use preg_quote because we want the user to be able to specify a |
1264 | + // regular expression subpattern. |
1265 | + $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i'; |
1266 | + if (preg_match($MYREQUEST['SEARCH'], 'test') === false) { |
1267 | + echo '<div class="error">Error: enter a valid regular expression as a search query.</div>'; |
1268 | + break; |
1269 | + } |
1270 | + } |
1271 | + |
1272 | + echo |
1273 | + '<div class="info"><table cellspacing=0><tbody>', |
1274 | + '<tr>', |
1275 | + '<th>',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'</th>', |
1276 | + '<th>',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'</th>', |
1277 | + '<th>',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'</th>', |
1278 | + '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>', |
1279 | + '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>', |
1280 | + '<th>',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'</th>'; |
1281 | + |
1282 | + if($fieldname=='info') { |
1283 | + $cols+=2; |
1284 | + echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>'; |
1285 | + } |
1286 | + echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>'; |
1287 | + |
1288 | + // builds list with alpha numeric sortable keys |
1289 | + // |
1290 | + $list = array(); |
1291 | + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) { |
1292 | + switch($MYREQUEST['SORT1']) { |
1293 | + case 'A': $k=sprintf('%015d-',$entry['access_time']); break; |
1294 | + case 'H': $k=sprintf('%015d-',$entry['num_hits']); break; |
1295 | + case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break; |
1296 | + case 'M': $k=sprintf('%015d-',$entry['mtime']); break; |
1297 | + case 'C': $k=sprintf('%015d-',$entry['creation_time']); break; |
1298 | + case 'T': $k=sprintf('%015d-',$entry['ttl']); break; |
1299 | + case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break; |
1300 | + case 'S': $k=''; break; |
1301 | + } |
1302 | + if (!$AUTHENTICATED) { |
1303 | + // hide all path entries if not logged in |
1304 | + $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry); |
1305 | + } else { |
1306 | + $list[$k.$entry[$fieldname]]=$entry; |
1307 | + } |
1308 | + } |
1309 | + |
1310 | + if ($list) { |
1311 | + |
1312 | + // sort list |
1313 | + // |
1314 | + switch ($MYREQUEST['SORT2']) { |
1315 | + case "A": krsort($list); break; |
1316 | + case "D": ksort($list); break; |
1317 | + } |
1318 | + |
1319 | + // output list |
1320 | + $i=0; |
1321 | + foreach($list as $k => $entry) { |
1322 | + if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) { |
1323 | + $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8'); |
1324 | + echo |
1325 | + '<tr class=tr-',$i%2,'>', |
1326 | + "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$field_value,'</a></td>', |
1327 | + '<td class="td-n center">',$entry['num_hits'],'</td>', |
1328 | + '<td class="td-n right">',$entry['mem_size'],'</td>', |
1329 | + '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>', |
1330 | + '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>', |
1331 | + '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>'; |
1332 | + |
1333 | + if($fieldname=='info') { |
1334 | + if($entry['ttl']) |
1335 | + echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>'; |
1336 | + else |
1337 | + echo '<td class="td-n center">None</td>'; |
1338 | + } |
1339 | + if ($entry['deletion_time']) { |
1340 | + |
1341 | + echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>'; |
1342 | + } else if ($MYREQUEST['OB'] == OB_USER_CACHE) { |
1343 | + |
1344 | + echo '<td class="td-last center">'; |
1345 | + echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]'; |
1346 | + echo '</td>'; |
1347 | + } else { |
1348 | + echo '<td class="td-last center"> </td>'; |
1349 | + } |
1350 | + echo '</tr>'; |
1351 | + $i++; |
1352 | + if ($i == $MYREQUEST['COUNT']) |
1353 | + break; |
1354 | + } |
1355 | + } |
1356 | + |
1357 | + } else { |
1358 | + echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>'; |
1359 | + } |
1360 | + echo <<< EOB |
1361 | + </tbody></table> |
1362 | +EOB; |
1363 | + |
1364 | + if ($list && $i < count($list)) { |
1365 | + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>'; |
1366 | + } |
1367 | + |
1368 | + echo <<< EOB |
1369 | + </div> |
1370 | +EOB; |
1371 | + break; |
1372 | + |
1373 | + |
1374 | +// ----------------------------------------------- |
1375 | +// Per-Directory System Cache Entries |
1376 | +// ----------------------------------------------- |
1377 | +case OB_SYS_CACHE_DIR: |
1378 | + if (!$AUTHENTICATED) { |
1379 | + break; |
1380 | + } |
1381 | + |
1382 | + echo <<<EOB |
1383 | + <div class=sorting><form>Scope: |
1384 | + <input type=hidden name=OB value={$MYREQUEST['OB']}> |
1385 | + <select name=SCOPE> |
1386 | +EOB; |
1387 | + echo |
1388 | + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>", |
1389 | + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>", |
1390 | + "</select>", |
1391 | + ", Sorting:<select name=SORT1>", |
1392 | + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>", |
1393 | + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>", |
1394 | + "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>", |
1395 | + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>", |
1396 | + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>", |
1397 | + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>", |
1398 | + '</select>', |
1399 | + '<select name=SORT2>', |
1400 | + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>', |
1401 | + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>', |
1402 | + '</select>', |
1403 | + '<select name=COUNT onChange="form.submit()">', |
1404 | + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>', |
1405 | + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>', |
1406 | + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>', |
1407 | + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>', |
1408 | + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>', |
1409 | + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>', |
1410 | + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>', |
1411 | + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>', |
1412 | + '</select>', |
1413 | + ", Group By Dir Level:<select name=AGGR>", |
1414 | + "<option value='' selected>None</option>"; |
1415 | + for ($i = 1; $i < 10; $i++) |
1416 | + echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>"; |
1417 | + echo '</select>', |
1418 | + ' <input type=submit value="GO!">', |
1419 | + '</form></div>', |
1420 | + |
1421 | + '<div class="info"><table cellspacing=0><tbody>', |
1422 | + '<tr>', |
1423 | + '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>', |
1424 | + '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>', |
1425 | + '<th>',sortheader('H','Total Hits', "&OB=".$MYREQUEST['OB']),'</th>', |
1426 | + '<th>',sortheader('Z','Total Size', "&OB=".$MYREQUEST['OB']),'</th>', |
1427 | + '<th>',sortheader('C','Avg. Hits', "&OB=".$MYREQUEST['OB']),'</th>', |
1428 | + '<th>',sortheader('A','Avg. Size', "&OB=".$MYREQUEST['OB']),'</th>', |
1429 | + '</tr>'; |
1430 | + |
1431 | + // builds list with alpha numeric sortable keys |
1432 | + // |
1433 | + $tmp = $list = array(); |
1434 | + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) { |
1435 | + $n = dirname($entry['filename']); |
1436 | + if ($MYREQUEST['AGGR'] > 0) { |
1437 | + $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n); |
1438 | + } |
1439 | + if (!isset($tmp[$n])) { |
1440 | + $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0); |
1441 | + } |
1442 | + $tmp[$n]['hits'] += $entry['num_hits']; |
1443 | + $tmp[$n]['size'] += $entry['mem_size']; |
1444 | + ++$tmp[$n]['ents']; |
1445 | + } |
1446 | + |
1447 | + foreach ($tmp as $k => $v) { |
1448 | + switch($MYREQUEST['SORT1']) { |
1449 | + case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break; |
1450 | + case 'T': $kn=sprintf('%015d-',$v['ents']); break; |
1451 | + case 'H': $kn=sprintf('%015d-',$v['hits']); break; |
1452 | + case 'Z': $kn=sprintf('%015d-',$v['size']); break; |
1453 | + case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break; |
1454 | + case 'S': $kn = $k; break; |
1455 | + } |
1456 | + $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']); |
1457 | + } |
1458 | + |
1459 | + if ($list) { |
1460 | + |
1461 | + // sort list |
1462 | + // |
1463 | + switch ($MYREQUEST['SORT2']) { |
1464 | + case "A": krsort($list); break; |
1465 | + case "D": ksort($list); break; |
1466 | + } |
1467 | + |
1468 | + // output list |
1469 | + $i = 0; |
1470 | + foreach($list as $entry) { |
1471 | + echo |
1472 | + '<tr class=tr-',$i%2,'>', |
1473 | + "<td class=td-0>",$entry[0],'</a></td>', |
1474 | + '<td class="td-n center">',$entry[1],'</td>', |
1475 | + '<td class="td-n center">',$entry[2],'</td>', |
1476 | + '<td class="td-n center">',$entry[3],'</td>', |
1477 | + '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>', |
1478 | + '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>', |
1479 | + '</tr>'; |
1480 | + |
1481 | + if (++$i == $MYREQUEST['COUNT']) break; |
1482 | + } |
1483 | + |
1484 | + } else { |
1485 | + echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>'; |
1486 | + } |
1487 | + echo <<< EOB |
1488 | + </tbody></table> |
1489 | +EOB; |
1490 | + |
1491 | + if ($list && $i < count($list)) { |
1492 | + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>'; |
1493 | + } |
1494 | + |
1495 | + echo <<< EOB |
1496 | + </div> |
1497 | +EOB; |
1498 | + break; |
1499 | + |
1500 | +// ----------------------------------------------- |
1501 | +// Version check |
1502 | +// ----------------------------------------------- |
1503 | +case OB_VERSION_CHECK: |
1504 | + echo <<<EOB |
1505 | + <div class="info"><h2>APC Version Information</h2> |
1506 | + <table cellspacing=0><tbody> |
1507 | + <tr> |
1508 | + <th></th> |
1509 | + </tr> |
1510 | +EOB; |
1511 | + if (defined('PROXY')) { |
1512 | + $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) ); |
1513 | + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss", False, $ctxt); |
1514 | + } else { |
1515 | + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss"); |
1516 | + } |
1517 | + if (!$rss) { |
1518 | + echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>'; |
1519 | + } else { |
1520 | + $apcversion = phpversion('apc'); |
1521 | + |
1522 | + preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match); |
1523 | + echo '<tr class="tr-0 center"><td>'; |
1524 | + if (version_compare($apcversion, $match[1], '>=')) { |
1525 | + echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>'; |
1526 | + $i = 3; |
1527 | + } else { |
1528 | + echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), |
1529 | + newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'"> |
1530 | + http://pecl.php.net/package/APC/'.$match[1].'</a> |
1531 | + </div>'; |
1532 | + $i = -1; |
1533 | + } |
1534 | + echo '</td></tr>'; |
1535 | + echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>'; |
1536 | + |
1537 | + preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match); |
1538 | + next($match[2]); next($match[2]); |
1539 | + |
1540 | + while (list(,$v) = each($match[2])) { |
1541 | + list(,$ver) = explode(' ', $v, 2); |
1542 | + if ($i < 0 && version_compare($apcversion, $ver, '>=')) { |
1543 | + break; |
1544 | + } else if (!$i--) { |
1545 | + break; |
1546 | + } |
1547 | + echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."</a></b><br><blockquote>"; |
1548 | + echo nl2br(htmlspecialchars(current($match[2]), ENT_QUOTES, 'UTF-8'))."</blockquote>"; |
1549 | + next($match[2]); |
1550 | + } |
1551 | + echo '</td></tr>'; |
1552 | + } |
1553 | + echo <<< EOB |
1554 | + </tbody></table> |
1555 | + </div> |
1556 | +EOB; |
1557 | + break; |
1558 | + |
1559 | +} |
1560 | + |
1561 | +echo <<< EOB |
1562 | + </div> |
1563 | +EOB; |
1564 | + |
1565 | +?> |
1566 | + |
1567 | +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> --> |
1568 | +</body> |
1569 | +</html> |
1570 | + |
1571 | + |
1572 | |
1573 | === added file 'files/_debug/info.php' |
1574 | --- files/_debug/info.php 1970-01-01 00:00:00 +0000 |
1575 | +++ files/_debug/info.php 2012-08-21 13:22:29 +0000 |
1576 | @@ -0,0 +1,3 @@ |
1577 | +<?php |
1578 | + |
1579 | +phpinfo(); |
1580 | |
1581 | === added directory 'files/charm' |
1582 | === added directory 'files/charm/nginx' |
1583 | === added file 'files/charm/nginx/etc_nginx_nginx.conf' |
1584 | --- files/charm/nginx/etc_nginx_nginx.conf 1970-01-01 00:00:00 +0000 |
1585 | +++ files/charm/nginx/etc_nginx_nginx.conf 2012-08-21 13:22:29 +0000 |
1586 | @@ -0,0 +1,58 @@ |
1587 | +user www-data; |
1588 | +worker_processes 4; |
1589 | +pid /var/run/nginx.pid; |
1590 | + |
1591 | +events { |
1592 | + worker_connections 8192; |
1593 | + multi_accept on; |
1594 | + use epoll; |
1595 | +} |
1596 | + |
1597 | +http { |
1598 | + ## |
1599 | + # Reverse |
1600 | + ## |
1601 | + set_real_ip_from 0.0.0.0/0; |
1602 | + real_ip_header X-Forwarded-For; |
1603 | + add_header X-UA-Compatible "IE=Edge,chrome=1"; |
1604 | + |
1605 | + ## |
1606 | + # Rockin Defaults |
1607 | + ## |
1608 | + sendfile on; |
1609 | + tcp_nopush on; |
1610 | + tcp_nodelay on; |
1611 | + keepalive_timeout 5; |
1612 | + types_hash_max_size 2048; |
1613 | + server_names_hash_bucket_size 64; |
1614 | + server_name_in_redirect off; |
1615 | + client_max_body_size 512k; |
1616 | + include /etc/nginx/mime.types; |
1617 | + default_type application/octet-stream; |
1618 | + index index.php index.html |
1619 | + |
1620 | + ## |
1621 | + # Logging Settings |
1622 | + ## |
1623 | + access_log /var/log/nginx/access.log; |
1624 | + error_log /var/log/nginx/error.log; |
1625 | + |
1626 | + ## |
1627 | + # Gzip Settings |
1628 | + ## |
1629 | + gzip on; |
1630 | + gzip_disable "msie6"; |
1631 | + gzip_vary on; |
1632 | + gzip_static on; |
1633 | + gzip_proxied any; |
1634 | + gzip_comp_level 4; |
1635 | + gzip_buffers 16 8k; |
1636 | + gzip_http_version 1.1; |
1637 | + gzip_types text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; |
1638 | + |
1639 | + ## |
1640 | + # Virtual Host Configs |
1641 | + ## |
1642 | + include /etc/nginx/conf.d/*.conf; |
1643 | + include /etc/nginx/sites-enabled/*; |
1644 | +} |
1645 | |
1646 | === added file 'files/charm/nginx/etc_nginx_sites-enabled_loadbalancer' |
1647 | --- files/charm/nginx/etc_nginx_sites-enabled_loadbalancer 1970-01-01 00:00:00 +0000 |
1648 | +++ files/charm/nginx/etc_nginx_sites-enabled_loadbalancer 2012-08-21 13:22:29 +0000 |
1649 | @@ -0,0 +1,51 @@ |
1650 | +# Default before peer relation is handled |
1651 | +proxy_cache_path /mnt/ramdisk/proxy-cache levels=1:2 keys_zone=proxycache:5m max_size=1000m; |
1652 | + |
1653 | +upstream backend { |
1654 | + server 127.0.0.1:8080; |
1655 | +} |
1656 | + |
1657 | +server { |
1658 | + listen 80 default; |
1659 | + server_name _; |
1660 | + location / { |
1661 | + set $no_cache ""; |
1662 | + |
1663 | + if ($request_method !~ ^(GET|HEAD)$) { |
1664 | + set $no_cache "1"; |
1665 | + } |
1666 | + |
1667 | + if ($no_cache = "1") { |
1668 | + add_header Set-Cookie "_mcnc=1; Max-Age=2; Path=/"; |
1669 | + add_header X-Microcachable "0"; |
1670 | + } |
1671 | + |
1672 | + if ($http_cookie ~* "_mcnc") { |
1673 | + set $no_cache "1"; |
1674 | + } |
1675 | + |
1676 | + proxy_no_cache $no_cache; |
1677 | + proxy_cache_bypass $no_cache; |
1678 | + |
1679 | + proxy_redirect http://backend /; |
1680 | + proxy_pass http://backend; |
1681 | + proxy_cache proxycache; |
1682 | + proxy_cache_key $scheme$host$request_method$request_uri; |
1683 | + proxy_cache_valid 200 60s; |
1684 | + proxy_cache_use_stale updating; |
1685 | + |
1686 | + proxy_set_header Host $host; |
1687 | + proxy_set_header X-Real-IP $remote_addr; |
1688 | + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
1689 | + |
1690 | + proxy_max_temp_file_size 1M; |
1691 | + |
1692 | + # Custom logging |
1693 | + log_format custom '$remote_addr - $remote_user [$time_local] ' |
1694 | + '"$request" $status $body_bytes_sent ' |
1695 | + '"$http_referer" "$http_user_agent" nocache:$no_cache'; |
1696 | + access_log /mnt/logs/microcache.log custom; |
1697 | + |
1698 | + } |
1699 | +} |
1700 | + |
1701 | |
1702 | === added file 'files/charm/nginx/etc_nginx_sites-enabled_wordpress' |
1703 | --- files/charm/nginx/etc_nginx_sites-enabled_wordpress 1970-01-01 00:00:00 +0000 |
1704 | +++ files/charm/nginx/etc_nginx_sites-enabled_wordpress 2012-08-21 13:22:29 +0000 |
1705 | @@ -0,0 +1,72 @@ |
1706 | +fastcgi_cache_path /mnt/ramdisk/phpfpm-cache levels=1:2 keys_zone=microcache:5M max_size=1G inactive=2h; |
1707 | + |
1708 | +server { |
1709 | + listen 8080 default; |
1710 | + server_name _; |
1711 | + access_log /mnt/access.log; |
1712 | + error_log /mnt/error.log; |
1713 | + root /var/www/; |
1714 | + index index.php index.html; |
1715 | + client_max_body_size 10m; |
1716 | + client_body_buffer_size 128k; |
1717 | + client_header_buffer_size 64k; |
1718 | + |
1719 | + location = /favicon.ico { |
1720 | + allow all; |
1721 | + log_not_found off; |
1722 | + access_log off; |
1723 | + } |
1724 | + |
1725 | + location = /robots.txt { |
1726 | + allow all; |
1727 | + log_not_found off; |
1728 | + access_log off; |
1729 | + } |
1730 | + |
1731 | + location ~* \.(js|css|png|jpg|jpeg|gif|ico|zip|gz|tar)$ { |
1732 | + log_not_found off; |
1733 | + access_log off; |
1734 | + expires max; |
1735 | + } |
1736 | + |
1737 | + location / { |
1738 | + # try_files "${document_root}/wp-content/cache/supercache/${host}/${uri}index.html" "${uri}/" "${uri}/index.html" $uri @rewrite; |
1739 | + try_files $uri $uri/ /index.php?q=$uri&$args; |
1740 | + } |
1741 | + |
1742 | + location ~ /\. { |
1743 | + access_log off; |
1744 | + log_not_found off; |
1745 | + deny all; |
1746 | + } |
1747 | + |
1748 | + location ~* /(fpm.www.status|fpm.www.ping)$ { |
1749 | + include /etc/nginx/fastcgi_params; |
1750 | + fastcgi_pass unix:/var/run/php5-fpm.sock; |
1751 | + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
1752 | + fastcgi_param SCRIPT_NAME $fastcgi_script_name; |
1753 | + fastcgi_param QUERY_STRING $args; |
1754 | + } |
1755 | + |
1756 | + location ~ \.php$ { |
1757 | + try_files $uri @rewrite; |
1758 | + include /etc/nginx/fastcgi_params; |
1759 | + fastcgi_pass unix:/var/run/php5-fpm.sock; |
1760 | + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
1761 | + fastcgi_param SCRIPT_NAME $fastcgi_script_name; |
1762 | + fastcgi_param QUERY_STRING $args; |
1763 | + } |
1764 | + |
1765 | + location @rewrite { |
1766 | + index index.php; |
1767 | + include /etc/nginx/fastcgi_params; |
1768 | + fastcgi_pass unix:/var/run/php5-fpm.sock; |
1769 | + fastcgi_buffers 256 4k; |
1770 | + fastcgi_intercept_errors on; |
1771 | + fastcgi_hide_header 'X-Generator'; |
1772 | + fastcgi_read_timeout 14400; |
1773 | + fastcgi_param SCRIPT_FILENAME $document_root/index.php; |
1774 | + fastcgi_param SCRIPT_NAME /index.php; |
1775 | + fastcgi_param QUERY_STRING $args; |
1776 | + } |
1777 | +} |
1778 | |
1779 | === added directory 'files/charm/php' |
1780 | === added file 'files/charm/php/php5-fpm_pool.d_www.conf' |
1781 | --- files/charm/php/php5-fpm_pool.d_www.conf 1970-01-01 00:00:00 +0000 |
1782 | +++ files/charm/php/php5-fpm_pool.d_www.conf 2012-08-21 13:22:29 +0000 |
1783 | @@ -0,0 +1,41 @@ |
1784 | +; -------------------------------------------------------------------- ; |
1785 | +; first pool |
1786 | +; -------------------------------------------------------------------- ; |
1787 | + |
1788 | +[www] |
1789 | +user = www-data |
1790 | +group = www-data |
1791 | + |
1792 | +listen = /var/run/php5-fpm.sock |
1793 | + |
1794 | +request_slowlog_timeout = 10s |
1795 | +slowlog = /mnt/logs/php-fpm/$pool.slowlog.log |
1796 | + |
1797 | +pm = dynamic |
1798 | +pm.max_children = 100 |
1799 | +pm.start_servers = 15 |
1800 | +pm.min_spare_servers = 4 |
1801 | +pm.max_spare_servers = 15 |
1802 | +pm.max_requests = 5000 |
1803 | +listen.backlog = -1 |
1804 | + |
1805 | +; http://url/status |
1806 | +; http://url/status?json |
1807 | +; http://url/status?html |
1808 | +pm.status_path = /fpm.$pool.status |
1809 | +ping.path = /fpm.$pool.ping |
1810 | +ping.response = "pong. $pool OK" |
1811 | + |
1812 | +request_terminate_timeout = 120s |
1813 | +rlimit_files = 131072 |
1814 | +rlimit_core = unlimited |
1815 | +catch_workers_output = no |
1816 | + |
1817 | +; this is untested will do this on a later update |
1818 | + |
1819 | +env[HOSTNAME] = $HOSTNAME |
1820 | +env[PATH] = $PATH |
1821 | +env[TMP] = /mnt/tmp |
1822 | +env[TMPDIR] = /mnt/tmp |
1823 | +env[TEMP] = /mnt/tmp |
1824 | +env[OHSO_POOL] = $pool |
1825 | |
1826 | === added file 'files/charm/php/php5_conf.d_apc.ini' |
1827 | --- files/charm/php/php5_conf.d_apc.ini 1970-01-01 00:00:00 +0000 |
1828 | +++ files/charm/php/php5_conf.d_apc.ini 2012-08-21 13:22:29 +0000 |
1829 | @@ -0,0 +1,13 @@ |
1830 | +extension=apc.so |
1831 | +apc.enable=1 |
1832 | +apc.shm_size = 1024M |
1833 | +apc.stat_ctime = 0 |
1834 | +apc.stat = 0 |
1835 | +apc.max_file_size = 2M |
1836 | +apc.write_lock = true |
1837 | +apc.mmap = /mnt/tmp/apc.XXXXXX |
1838 | +apc.ttl = 0 |
1839 | +apc.user_ttl = 7200 |
1840 | +apc.gc_ttl = 7200 |
1841 | +apc.use_request_time = 1 |
1842 | +apc.file_md5 = 1 |
1843 | |
1844 | === added file 'hooks/config-changed' |
1845 | --- hooks/config-changed 1970-01-01 00:00:00 +0000 |
1846 | +++ hooks/config-changed 2012-08-21 13:22:29 +0000 |
1847 | @@ -0,0 +1,54 @@ |
1848 | +#!/bin/bash |
1849 | + |
1850 | +set -ue |
1851 | + |
1852 | +source inc/common |
1853 | + |
1854 | +tuning_level=`config-get tuning` |
1855 | +# Make it lower case |
1856 | +tuning_level=${tuning_level,,} |
1857 | + |
1858 | +wp_content_repo=`config-get wp-content` |
1859 | +expose_info=`config-get debug` |
1860 | +expose_info=${expose_info,,} |
1861 | + |
1862 | +if [ ! -f $config_file_path ]; then |
1863 | + juju-log "Nothing to configure, since nothing is installed" |
1864 | + exit 0 |
1865 | +fi |
1866 | + |
1867 | +juju-log "Show details? $expose_info" |
1868 | + |
1869 | +if [ "$expose_info" == "yes" ]; then |
1870 | + rsync -az files/_debug $wp_install_path/ |
1871 | +else |
1872 | + rm -rf $wp_install_path/_debug |
1873 | +fi |
1874 | + |
1875 | +juju-log "I will be using this tuning level: $tuning_level" |
1876 | + |
1877 | +if [ "$tuning_level" == "optimized" ]; then |
1878 | + # First and foremost, we need to disable the ability to edit |
1879 | + # themes and upload/update plugins. This breaks a scale-out |
1880 | + # environment. It's sad but true. If you want to update a plugin |
1881 | + # install a theme, etc; take a look at the README. |
1882 | + make_optimized |
1883 | +elif [ "$tuning_level" == "single" ]; then |
1884 | + # We need to prepare an NFS mount, because someone is probably |
1885 | + # going to try to scale out. We also need to vamp up caching. |
1886 | + make_single |
1887 | +elif [ "$tuning_level" == "bare" ]; then |
1888 | + # Okay, you know what you're doing. You're probably going to |
1889 | + # use Gluster to stream-line your files, so you don't need to |
1890 | + # disable anything. We trust you to do what you need to. |
1891 | + make_bare |
1892 | +else |
1893 | + juju-log "Not sure about that tuning level." |
1894 | + exit 1 |
1895 | +fi |
1896 | + |
1897 | +do_vcs $wp_content_repo |
1898 | + |
1899 | +chown -R www-data.www-data $wp_install_path |
1900 | + |
1901 | +. hooks/restart |
1902 | |
1903 | === added symlink 'hooks/db-relation-broken' |
1904 | === target is u'db-relation-departed' |
1905 | === modified file 'hooks/db-relation-changed' |
1906 | --- hooks/db-relation-changed 2012-06-18 20:28:16 +0000 |
1907 | +++ hooks/db-relation-changed 2012-08-21 13:22:29 +0000 |
1908 | @@ -1,5 +1,6 @@ |
1909 | #!/bin/bash |
1910 | |
1911 | +<<<<<<< TREE |
1912 | set -eu # -x for verbose logging to juju debug-log |
1913 | |
1914 | UPLOAD_PATH="/var/www/wp-uploads" |
1915 | @@ -9,24 +10,31 @@ |
1916 | |
1917 | # Check we haven't already been setup. |
1918 | config_file_path="/etc/wordpress/config-default.php" |
1919 | - |
1920 | -# Get the database settings; if not set, wait for this hook to be |
1921 | -# invoked again |
1922 | +======= |
1923 | +set -eu |
1924 | + |
1925 | +juju-log "We've got a db" |
1926 | + |
1927 | +source inc/common |
1928 | + |
1929 | +if [ -f "$config_file_path" ]; then |
1930 | + # No longer to quietly in to that good night. Update the wp-config file with new DB values |
1931 | + juju-log "WordPress is already setup, just silently going away" |
1932 | + exit 0 |
1933 | +fi |
1934 | +>>>>>>> MERGE-SOURCE |
1935 | + |
1936 | database=`relation-get database` |
1937 | -if [ -z "$database" ] ; then |
1938 | - exit 0 # wait for future handshake from database service unit |
1939 | -fi |
1940 | - |
1941 | -# Our protocol on this interface ensures that all or none of the |
1942 | -# settings are set. But we can verify the setting or the values if |
1943 | -# more error checking if desired. |
1944 | user=`relation-get user` |
1945 | password=`relation-get password` |
1946 | host=`relation-get private-address` |
1947 | |
1948 | -# Create an internal secret key for wordpress; this is unrelated to |
1949 | -# the password generated for the admin user of wordpress |
1950 | +if [ -z "$database" ] ; then |
1951 | + exit 0 |
1952 | +fi |
1953 | + |
1954 | secret_key=`pwgen 10 1` |
1955 | +<<<<<<< TREE |
1956 | |
1957 | juju-log "Creating appropriate upload paths and directories" |
1958 | # Setup appropriate upload paths and directories |
1959 | @@ -37,10 +45,39 @@ |
1960 | chmod 0744 $UPLOAD_PATH |
1961 | chmod 0770 "$UPLOAD_PATH/$hostname" |
1962 | chown -R root:www-data "/var/www/$hostname/wp-content" |
1963 | +======= |
1964 | +echo $secret_key > wp_secret |
1965 | +source "/usr/share/charm-helper/sh/net.sh" |
1966 | + |
1967 | +## |
1968 | +# OH COME ON WORDPRESS.ORG NO VALID SSL CERTIFICATE? |
1969 | +# Psh, whatever, plain-text for now. #blamenacin |
1970 | +# https://twitter.com/#!/marcoceppi/status/181570187655520260 |
1971 | +# I was wrong, we need to use something other than WGET, like cURL |
1972 | +LATEST_WORDPRESS="http://wordpress.org/latest.tar.gz" |
1973 | +DOWNLOAD=`ch_get_file "$LATEST_WORDPRESS" "http://wordpress.org/latest.tar.gz.sha1"` |
1974 | +## |
1975 | + |
1976 | +if [ ! -f "$DOWNLOAD" ] || [ -z "$DOWNLOAD" ]; then |
1977 | + juju-log "Failed to retrieve $LATEST_WORDPRESS" |
1978 | + exit 1 |
1979 | +fi |
1980 | + |
1981 | +juju-log "Extract ALL THE FILES" |
1982 | +tar -xzf $DOWNLOAD |
1983 | + |
1984 | +mkdir -p $wp_install_path |
1985 | + |
1986 | +juju-log "Move them in to place, but just 'drop' them in place." |
1987 | +rsync -az wordpress/ $wp_install_path |
1988 | + |
1989 | +juju-log "Clean up" |
1990 | +rm -rf wordpress |
1991 | +>>>>>>> MERGE-SOURCE |
1992 | |
1993 | juju-log "Writing wordpress config file $config_file_path" |
1994 | # Write the wordpress config |
1995 | -cat > $config_file_path <<EOF |
1996 | +cat > $config_info_path <<EOF |
1997 | <?php |
1998 | define('DB_NAME', '$database'); |
1999 | define('DB_USER', '$user'); |
2000 | @@ -48,49 +85,60 @@ |
2001 | define('DB_HOST', '$host'); |
2002 | define('SECRET_KEY', '$secret_key'); |
2003 | |
2004 | -#This will disable the update notification. |
2005 | -define('WP_CORE_UPDATE', false); |
2006 | +define('WP_CACHE', true); |
2007 | + |
2008 | +/* |
2009 | +define('AUTH_KEY', '$secret_key'); |
2010 | +define('SECURE_AUTH_KEY', '$secret_key'); |
2011 | +define('LOGGED_IN_KEY', '$secret_key'); |
2012 | +define('NONCE_KEY', '$secret_key'); |
2013 | +*/ |
2014 | |
2015 | \$table_prefix = 'wp_'; |
2016 | -\$server = '$host'; |
2017 | -\$loginsql = '$user'; |
2018 | -\$passsql = '$password'; |
2019 | -\$base = '$database'; |
2020 | -\$upload_path = '/var/www/wp-uploads/$hostname'; |
2021 | -\$upload_url_path = 'http://$hostname/wp-uploads'; |
2022 | -?> |
2023 | -EOF |
2024 | + |
2025 | +EOF |
2026 | + |
2027 | +cat > $config_file_path <<EOF |
2028 | +<?php |
2029 | + |
2030 | +/* That's all, stop editing! Happy blogging. */ |
2031 | + |
2032 | +/** Absolute path to the WordPress directory. */ |
2033 | +if ( !defined('ABSPATH') ) |
2034 | + define('ABSPATH', dirname(__FILE__) . '/'); |
2035 | + |
2036 | +/** Pull in the config information */ |
2037 | +require_once(ABSPATH . 'wp-info.php'); |
2038 | +require_once(ABSPATH . 'wp-overrides.php'); |
2039 | + |
2040 | +/** Sets up WordPress vars and included files. */ |
2041 | +require_once(ABSPATH . 'wp-settings.php'); |
2042 | + |
2043 | +remove_filter('template_redirect', 'redirect_canonical'); |
2044 | + |
2045 | +EOF |
2046 | + |
2047 | chmod 0644 $config_file_path |
2048 | - |
2049 | -# Write the apache config |
2050 | -# XXX a future branch will change this to use augtool |
2051 | -apache_config_file_path="/etc/apache2/sites-available/$hostname" |
2052 | -juju-log "Writing apache config file $apache_config_file_path" |
2053 | -cat > $apache_config_file_path <<EOF |
2054 | -<VirtualHost *:80> |
2055 | - ServerName $hostname |
2056 | - DocumentRoot /var/www/$hostname |
2057 | - Options All |
2058 | - ErrorLog /var/log/apache2/wp-error.log |
2059 | - TransferLog /var/log/apache2/wp-access.log |
2060 | - # Store uploads in /var/www/wp-uploads/$0 |
2061 | - RewriteEngine On |
2062 | - RewriteRule ^/wp-uploads/(.*)$ /var/www/wp-uploads/%%{HTTP_HOST}/\$1 |
2063 | -</VirtualHost> |
2064 | -EOF |
2065 | -chmod 0644 $apache_config_file_path |
2066 | - |
2067 | -# Configure apache |
2068 | -juju-log "Enabling apache modules: rewrite, vhost_alias" |
2069 | -a2enmod rewrite |
2070 | -a2enmod vhost_alias |
2071 | +touch $config_override_path |
2072 | + |
2073 | juju-log "Enabling apache site: $hostname" |
2074 | +<<<<<<< TREE |
2075 | a2ensite $hostname |
2076 | a2dissite default |
2077 | |
2078 | # Restart apache |
2079 | juju-log "Restarting apache2 service" |
2080 | /etc/init.d/apache2 restart |
2081 | +======= |
2082 | + |
2083 | +chown -R www-data.www-data $wp_install_path |
2084 | + |
2085 | +. hooks/config-changed |
2086 | + |
2087 | +# Restart nginx |
2088 | +juju-log "Restarting nginx service" |
2089 | +service nginx restart |
2090 | +>>>>>>> MERGE-SOURCE |
2091 | |
2092 | # Make it publicly visible, once the wordpress service is exposed |
2093 | open-port 80/tcp |
2094 | |
2095 | === added file 'hooks/db-relation-departed' |
2096 | --- hooks/db-relation-departed 1970-01-01 00:00:00 +0000 |
2097 | +++ hooks/db-relation-departed 2012-08-21 13:22:29 +0000 |
2098 | @@ -0,0 +1,5 @@ |
2099 | +#!/bin/bash |
2100 | + |
2101 | +source inc/common |
2102 | + |
2103 | +rm -f $config_file_path |
2104 | |
2105 | === modified file 'hooks/install' |
2106 | --- hooks/install 2011-10-18 06:11:17 +0000 |
2107 | +++ hooks/install 2012-08-21 13:22:29 +0000 |
2108 | @@ -1,3 +1,58 @@ |
2109 | #!/bin/bash |
2110 | |
2111 | -apt-get -y install wordpress pwgen |
2112 | +add-apt-repository ppa:charmers/charm-helpers |
2113 | + |
2114 | +apt-get update && apt-get -y upgrade |
2115 | +apt-get -y install php5-memcache mysql-client pwgen nginx php5 php5-fpm php-apc mailutils php-mail sysstat php5-mysql php5-mcrypt charm-helper-sh s3cmd php5-curl rsync nfs-common bzr git-core mktemp |
2116 | + |
2117 | +modprobe nfs |
2118 | + |
2119 | +juju-log "Removing PHP Default Cron ..." |
2120 | +rm -f /etc/cron.d/php5 |
2121 | + |
2122 | +juju-log "Making /mnt/tmp dir ..." |
2123 | +mkdir -p /mnt/tmp |
2124 | +chmod 1777 /mnt/tmp |
2125 | + |
2126 | +juju-log "Making /mnt/logs ..." |
2127 | +mkdir -p /mnt/logs/php-fpm |
2128 | +chmod -R 1777 /mnt/logs |
2129 | + |
2130 | +## dont make this an actual ramdisk until later when size can be safely tested |
2131 | +## just using plain disk cache for now |
2132 | +juju-log "Making Ramdisk mount point and config ..." |
2133 | +mkdir -p /mnt/ramdisk/proxy-cache |
2134 | +mkdir -p /mnt/ramdisk/phpfpm-cache |
2135 | +chmod -R 1777 /mnt/ramdisk |
2136 | + |
2137 | +juju-log "Cleaning any old or default nginx site configs ..." |
2138 | +rm -f /etc/nginx/sites-enabled/* |
2139 | +rm -f /etc/nginx/conf.d/* |
2140 | + |
2141 | +juju-log "Installing Nginx common config ..." |
2142 | +rm -f /etc/nginx/nginx.conf |
2143 | +install -o root -g root -m 0644 files/charm/nginx/etc_nginx_nginx.conf /etc/nginx/nginx.conf |
2144 | + |
2145 | +juju-log "Installing Nginx actual site config ..." |
2146 | +#rm -f /etc/nginx/sites-available/ |
2147 | +install -o root -g root -m 0644 files/charm/nginx/etc_nginx_sites-enabled_wordpress /etc/nginx/sites-available/wordpress |
2148 | +ln -sf ../sites-available/wordpress /etc/nginx/sites-enabled/wordpress |
2149 | + |
2150 | +juju-log "Installing Nginx loadbal config ..." |
2151 | +rm -f /etc/nginx/sites-available/loadbalancer |
2152 | +install -o root -g root -m 0644 files/charm/nginx/etc_nginx_sites-enabled_loadbalancer /etc/nginx/sites-available/loadbalancer |
2153 | +ln -sf ../sites-available/loadbalancer /etc/nginx/sites-enabled/loadbalancer |
2154 | + |
2155 | +juju-log "Installing PHP-FPM pool configs ..." |
2156 | +rm -f /etc/php5/fpm/pool.d/* |
2157 | +install -o root -g root -m 0644 files/charm/php/php5-fpm_pool.d_www.conf /etc/php5/fpm/pool.d/www.conf |
2158 | + |
2159 | +juju-log "Moving PHP and Nginx var dirs to /mnt storage ..." |
2160 | +rsync -avz /var/lib/nginx /mnt/ && rm -rf /var/lib/nginx && ln -s /mnt/nginx /var/lib/ |
2161 | +rsync -avz /var/lib/php5 /mnt/ && rm -rf /var/lib/php5 && ln -s /mnt/php5 /var/lib/ |
2162 | + |
2163 | +juju-log "Restarting Services ..." |
2164 | +service php5-fpm restart |
2165 | +service nginx restart |
2166 | + |
2167 | +juju-log "So, environment is setup. We'll wait for some hooks to fire off before we get all crazy" |
2168 | |
2169 | === added symlink 'hooks/loadbalancer-relation-broken' |
2170 | === target is u'loadbalancer-relation-joined' |
2171 | === added symlink 'hooks/loadbalancer-relation-departed' |
2172 | === target is u'loadbalancer-relation-joined' |
2173 | === added file 'hooks/loadbalancer-relation-joined' |
2174 | --- hooks/loadbalancer-relation-joined 1970-01-01 00:00:00 +0000 |
2175 | +++ hooks/loadbalancer-relation-joined 2012-08-21 13:22:29 +0000 |
2176 | @@ -0,0 +1,124 @@ |
2177 | +#!/usr/bin/env python |
2178 | +# |
2179 | +# reverseproxy-relation-changed - hook for when reverse proxy relation changes |
2180 | +# |
2181 | +# Copyright (C) 2011 Canonical Ltd. |
2182 | +# Author: Clint Byrum <clint.byrum@canonical.com> |
2183 | +# |
2184 | +# This program is free software: you can redistribute it and/or modify |
2185 | +# it under the terms of the GNU General Public License as published by |
2186 | +# the Free Software Foundation, either version 3 of the License, or |
2187 | +# (at your option) any later version. |
2188 | +# |
2189 | +# This program is distributed in the hope that it will be useful, |
2190 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2191 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2192 | +# GNU General Public License for more details. |
2193 | +# |
2194 | +# You should have received a copy of the GNU General Public License |
2195 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2196 | +# |
2197 | + |
2198 | +import sys |
2199 | +import os |
2200 | +import subprocess |
2201 | +import json |
2202 | +import tempfile |
2203 | +import glob |
2204 | + |
2205 | +from socket import getaddrinfo |
2206 | + |
2207 | +remote_unit = os.environ.get("JUJU_REMOTE_UNIT") |
2208 | + |
2209 | +service_name, _ = remote_unit.split("/") |
2210 | + |
2211 | +# TODO: maybe load this from disk for easier customization |
2212 | +t1 = """# Generated by juju |
2213 | +proxy_cache_path /mnt/ramdisk/proxy-cache levels=1:2 keys_zone=proxycache:5m max_size=1000m; |
2214 | +""" |
2215 | +# servers will go here |
2216 | +template = """ |
2217 | +server { |
2218 | + listen 80 default; |
2219 | + server_name _; |
2220 | + |
2221 | + location / { |
2222 | + set $no_cache ""; |
2223 | + |
2224 | + if ($request_method !~ ^(GET|HEAD)$) { |
2225 | + set $no_cache "1"; |
2226 | + } |
2227 | + |
2228 | + if ($no_cache = "1") { |
2229 | + add_header Set-Cookie "_mcnc=1; Max-Age=30; Path=/"; |
2230 | + add_header X-Microcachable "0"; |
2231 | + } |
2232 | + |
2233 | + if ($http_cookie ~* "_mcnc") { |
2234 | + set $no_cache "1"; |
2235 | + } |
2236 | + |
2237 | + proxy_no_cache $no_cache; |
2238 | + proxy_cache_bypass $no_cache; |
2239 | + |
2240 | + proxy_redirect http://backend /; |
2241 | + proxy_pass http://backend; |
2242 | + proxy_cache proxycache; |
2243 | + proxy_cache_key $scheme$host$request_method$request_uri; |
2244 | + proxy_cache_valid 200 60s; |
2245 | + proxy_cache_use_stale updating; |
2246 | + |
2247 | + proxy_set_header Host $host; |
2248 | + proxy_set_header X-Real-IP $remote_addr; |
2249 | + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
2250 | + proxy_set_header X-UA-Compatible "IE=Edge,chrome=1"; |
2251 | + |
2252 | + proxy_max_temp_file_size 1M; |
2253 | + } |
2254 | +} |
2255 | +""" |
2256 | + |
2257 | +units = [] |
2258 | +p = subprocess.Popen("relation-list", stdout=subprocess.PIPE) |
2259 | +for unit in p.stdout: |
2260 | + units.append(unit.strip()) |
2261 | + |
2262 | +print units |
2263 | + |
2264 | +servers = """ |
2265 | +upstream backend { |
2266 | + server 127.0.0.1:8080; |
2267 | +""" |
2268 | +for unit in units: |
2269 | + p = subprocess.Popen(["relation-get", "private-address", unit], |
2270 | + stdout=subprocess.PIPE, close_fds=True) |
2271 | + paddress = p.stdout.read().strip() |
2272 | + p.wait() |
2273 | + # Add all configured units: |
2274 | + servers += (" server %s:8080;\n" % (paddress)) |
2275 | +servers += '}' |
2276 | + |
2277 | +print servers |
2278 | + |
2279 | +with tempfile.NamedTemporaryFile(dir="/etc/nginx/sites-available/",prefix="loadbalancer", delete=False) as conf: |
2280 | + conf.write(t1 + servers + template) |
2281 | + try: |
2282 | + os.unlink("/etc/nginx/sites-available/loadbalancer.old") |
2283 | + except: |
2284 | + pass |
2285 | + try: |
2286 | + os.rename("/etc/nginx/sites-available/loadbalancer","/etc/nginx/sites-available/loadbalancer.old") |
2287 | + except: |
2288 | + pass |
2289 | + try: |
2290 | + os.rename(conf.name, "/etc/nginx/sites-available/loadbalancer") |
2291 | + except: |
2292 | + os.unlink(conf.name) |
2293 | + |
2294 | + |
2295 | + |
2296 | +# Just in case haproxy wouldn't start because of empty/bad configs before, start it now |
2297 | +subprocess.call(["service", "nginx", "start"]) |
2298 | +subprocess.check_call(["service", "nginx", "reload"]) |
2299 | + |
2300 | +subprocess.check_call(["open-port", "80"]) |
2301 | |
2302 | === added symlink 'hooks/nfs-relation-broken' |
2303 | === target is u'nfs-relation-departed' |
2304 | === added file 'hooks/nfs-relation-changed' |
2305 | --- hooks/nfs-relation-changed 1970-01-01 00:00:00 +0000 |
2306 | +++ hooks/nfs-relation-changed 2012-08-21 13:22:29 +0000 |
2307 | @@ -0,0 +1,28 @@ |
2308 | +#!/bin/bash |
2309 | + |
2310 | +set -eu |
2311 | + |
2312 | +juju-log "We've got a mount" |
2313 | +source inc/common |
2314 | + |
2315 | +options=`relation-get options` |
2316 | +mountpoint=`relation-get mountpoint` |
2317 | +fstype=`relation-get fstype` |
2318 | +host=`relation-get private-address` |
2319 | + |
2320 | +if [ -z "$fstype" ] ; then |
2321 | + juju-log "Going to wait for some real data" |
2322 | + exit 0 |
2323 | +fi |
2324 | + |
2325 | +# Write this out to our .nfs-mount file |
2326 | +cat > .nfs-mount <<EOF |
2327 | +#!/bin/bash |
2328 | +MOUNT_TYPE=$fstype |
2329 | +MOUNT_OPS=$options |
2330 | +MOUNT_SERVER=$host |
2331 | +MOUNT_PATH=$mountpoint |
2332 | + |
2333 | +EOF |
2334 | + |
2335 | +. hooks/config-changed |
2336 | |
2337 | === added file 'hooks/nfs-relation-departed' |
2338 | --- hooks/nfs-relation-departed 1970-01-01 00:00:00 +0000 |
2339 | +++ hooks/nfs-relation-departed 2012-08-21 13:22:29 +0000 |
2340 | @@ -0,0 +1,20 @@ |
2341 | +#!/bin/bash |
2342 | + |
2343 | +set -eu |
2344 | + |
2345 | +juju-log "We've got a mount" |
2346 | +source inc/common |
2347 | + |
2348 | +if [ ! -f .nfs-mount ]; then |
2349 | + juju-log "I guess we've already done this." |
2350 | + exit 0 |
2351 | +fi |
2352 | + |
2353 | +source .nfs-mount |
2354 | +umount /mnt/wordpress |
2355 | + |
2356 | +rm -f .nfs-mount |
2357 | + |
2358 | +juju-log "Fairwell nfs mount, we hardly knew you" |
2359 | + |
2360 | +. hooks/config-changed |
2361 | |
2362 | === added file 'hooks/restart' |
2363 | --- hooks/restart 1970-01-01 00:00:00 +0000 |
2364 | +++ hooks/restart 2012-08-21 13:22:29 +0000 |
2365 | @@ -0,0 +1,4 @@ |
2366 | +#!/bin/bash |
2367 | + |
2368 | +. hooks/stop |
2369 | +. hooks/start |
2370 | |
2371 | === modified file 'hooks/start' |
2372 | --- hooks/start 2011-02-07 22:23:02 +0000 |
2373 | +++ hooks/start 2012-08-21 13:22:29 +0000 |
2374 | @@ -1,1 +1,4 @@ |
2375 | #!/bin/bash |
2376 | + |
2377 | +service php5-fpm restart |
2378 | +service nginx restart |
2379 | |
2380 | === modified file 'hooks/stop' |
2381 | --- hooks/stop 2011-10-14 10:22:29 +0000 |
2382 | +++ hooks/stop 2012-08-21 13:22:29 +0000 |
2383 | @@ -1,3 +1,6 @@ |
2384 | #!/bin/bash |
2385 | -juju-log "Stopping apache" |
2386 | -/etc/init.d/apache2 stop |
2387 | \ No newline at end of file |
2388 | + |
2389 | +service php5-fpm stop |
2390 | +service nginx stop |
2391 | + |
2392 | + |
2393 | |
2394 | === modified symlink 'hooks/upgrade-charm' (properties changed: -x to +x) |
2395 | === target was u'install' |
2396 | --- hooks/upgrade-charm 1970-01-01 00:00:00 +0000 |
2397 | +++ hooks/upgrade-charm 2012-08-21 13:22:29 +0000 |
2398 | @@ -0,0 +1,11 @@ |
2399 | +#!/bin/bash |
2400 | + |
2401 | +# Run the install again! |
2402 | +hooks/install |
2403 | + |
2404 | +wp_install_path="/var/www/" |
2405 | + |
2406 | +chown -R www-data.www-data $wp_install_path |
2407 | + |
2408 | +source hooks/config-changed |
2409 | +source hooks/restart |
2410 | |
2411 | === added directory 'inc' |
2412 | === added file 'inc/common' |
2413 | --- inc/common 1970-01-01 00:00:00 +0000 |
2414 | +++ inc/common 2012-08-21 13:22:29 +0000 |
2415 | @@ -0,0 +1,139 @@ |
2416 | +#!/bin/bash |
2417 | + |
2418 | + |
2419 | +hostname=`unit-get public-address` |
2420 | +private_name=`hostname -f` |
2421 | + |
2422 | +wp_install_path="/var/www/" |
2423 | +config_file_path="$wp_install_path/wp-config.php" |
2424 | +config_info_path="$wp_install_path/wp-info.php" |
2425 | +config_override_path="$wp_install_path/wp-overrides.php" |
2426 | + |
2427 | +#### |
2428 | +## The only hook who should ever remove the NFS mount is the nfs-relation-(departed|broken) hook |
2429 | +## Everyone else should just assume it's there or try to mount it. We don't want to loose people's |
2430 | +## data, they get mad when that happens |
2431 | +#### |
2432 | + |
2433 | +make_bare() |
2434 | +{ |
2435 | + # Un-do APC |
2436 | + rm -f /etc/php5/conf.d/apc.ini |
2437 | + # IF there is an NFS mount, get everything out of it |
2438 | + if [ -f .nfs-mount ]; then # Looks like someone got fancy with NFS |
2439 | + if [ -L $wp_install_path/wp-content ]; then # Check if we actually have a symlink |
2440 | + rm -f $wp_install_path/wp-content |
2441 | + rsync -az /mnt/wordpress/wp-content $wp_install_path |
2442 | + fi |
2443 | + fi |
2444 | + |
2445 | + echo "<?php" > $config_override_path |
2446 | + juju-log "We are now bare" |
2447 | +} |
2448 | + |
2449 | +make_single() |
2450 | +{ |
2451 | + make_bare |
2452 | + juju-log "Installing PHP apc.ini ..." |
2453 | + rm -f /etc/php5/conf.d/apc.ini |
2454 | + install -o root -g root -m 0644 files/charm/php/php5_conf.d_apc.ini /etc/php5/conf.d/apc.ini |
2455 | + do_nfs |
2456 | + juju-log "We are now single" |
2457 | +} |
2458 | + |
2459 | +make_optimized() |
2460 | +{ |
2461 | + make_single |
2462 | + cat > $config_override_path <<EOF |
2463 | +<?php |
2464 | +define('DISALLOW_FILE_MODS', TRUE); |
2465 | +EOF |
2466 | + juju-log "We are now optimized" |
2467 | +} |
2468 | + |
2469 | +do_nfs() |
2470 | +{ |
2471 | + if [ -f .nfs-mount ]; then |
2472 | + # This has all the NFS mount stuff in it |
2473 | + source .nfs-mount |
2474 | + mkdir -p /mnt/wordpress |
2475 | + if grep -qs '/mnt/wordpress' /proc/mounts; then |
2476 | + juju-log "We're already mounted." |
2477 | + else |
2478 | + mount -t $MOUNT_TYPE -o $MOUNT_OPS $MOUNT_SERVER:$MOUNT_PATH /mnt/wordpress |
2479 | + if [ $? -ne 0 ]; then |
2480 | + juju-log "Could not connect to file-server" |
2481 | + exit 1 # OH THE HUMANITY OF IT ALL |
2482 | + fi |
2483 | + if [ ! -d /mnt/wordpress/wp-content ]; then |
2484 | + rsync -az $wp_install_path/wp-content /mnt/wordpress/ |
2485 | + fi |
2486 | + |
2487 | + mv $wp_install_path/wp-content $wp_install_path/wp-content.bak.$(date +%Y%m%d-%H%M%S) && rm -rf $wp_install_path/wp-content |
2488 | + ln -s /mnt/wordpress/wp-content $wp_install_path |
2489 | + juju-log "Mounted NFS" |
2490 | + fi |
2491 | + else |
2492 | + juju-log "There is no nfs mount, not sure what to do, so we'll just bail" |
2493 | + fi |
2494 | +} |
2495 | + |
2496 | +do_vcs() |
2497 | +{ |
2498 | + local NEW_REPO_URL="$1" |
2499 | + |
2500 | + if [ -z "$NEW_REPO_URL" ]; then |
2501 | + rm -f .wp-repo |
2502 | + return 0 |
2503 | + fi |
2504 | + |
2505 | + if [ -f .wp-repo ]; then |
2506 | + source .wp-repo |
2507 | + else |
2508 | + REPO_URL="" |
2509 | + fi |
2510 | + |
2511 | + if [ "$NEW_REPO_URL" != "$REPO_URL" ]; then |
2512 | + # We need to determine what kind of URL this is |
2513 | + if [ $(echo "$NEW_REPO_URL" | egrep -Ec "^(lp:\~|bzr:\/\/|bzr+ssh:\/\/)") -eq 1 ]; then |
2514 | + local repo_type="bzr" |
2515 | + local cmd="branch" |
2516 | + elif [ $(echo "$NEW_REPO_URL" | egrep -Ec "(^git@|^git:\/\/|\.git$)") -gt 0 ]; then |
2517 | + local repo_type="git" |
2518 | + local cmd="clone" |
2519 | + else |
2520 | + return 1 |
2521 | + fi |
2522 | + |
2523 | + repo_path=$(mktemp -d) |
2524 | + $repo_type $cmd $NEW_REPO_URL $repo_path |
2525 | + # Write all our new data to disk |
2526 | + cat > .wp-repo <<EOF |
2527 | +#!/bin/bash |
2528 | +REPO_TYPE=$repo_type |
2529 | +REPO_URL=$NEW_REPO_URL |
2530 | +REPO_PATH=$repo_path |
2531 | +REPO_CMD=$cmd |
2532 | + |
2533 | +EOF |
2534 | + source .wp-repo # Just so the rest of this can run all willy nilly |
2535 | + fi |
2536 | + |
2537 | + if [ ! -d "$REPO_PATH" ]; then |
2538 | + mkdir -p "$REPO_PATH" |
2539 | + $REPO_TYPE $REPO_CMD $REPO_URL $REPO_PATH |
2540 | + fi |
2541 | + |
2542 | + local cwd=$(pwd) |
2543 | + cd $REPO_PATH |
2544 | + $REPO_TYPE pull |
2545 | + cd $cwd |
2546 | + |
2547 | + # This will clean up anything deleted from wp-content specifically |
2548 | + rsync -az --delete $REPO_PATH/wp-content/ $wp_install_path/wp-content/ |
2549 | + # This is just incase people have modifications outside of the wp-content directory |
2550 | + rsync -az $REPO_PATH/ $wp_install_path/ |
2551 | + |
2552 | + # This should be an --exclude flag in the RSYNC command, but I'm not quite sure how to make that work properly. |
2553 | + rm -rf $wp_install_path/.$REPO_TYPE |
2554 | +} |
2555 | |
2556 | === modified file 'metadata.yaml' |
2557 | --- metadata.yaml 2012-05-22 22:35:00 +0000 |
2558 | +++ metadata.yaml 2012-08-21 13:22:29 +0000 |
2559 | @@ -1,16 +1,22 @@ |
2560 | name: wordpress |
2561 | +<<<<<<< TREE |
2562 | summary: "WordPress is a full featured web blogging tool" |
2563 | maintainer: Clint Byrum <clint@ubuntu.com> |
2564 | +======= |
2565 | +summary: "WordPress is a full featured web blogging tool, this charm deploys it." |
2566 | +maintainer: Marco Ceppi <marco@ceppi.net> |
2567 | +>>>>>>> MERGE-SOURCE |
2568 | description: | |
2569 | - WordPress is a full featured web blogging tool: |
2570 | - - Instant publishing (no rebuilding) |
2571 | - - Comment pingback support with spam protection |
2572 | - - Non-crufty URLs |
2573 | - - Themable |
2574 | - - Plugin support |
2575 | + This will install and setup WordPress optimized to run in the cloud. This install, in particular, will |
2576 | + place Ngnix and php-fpm configured to scale horizontally with Nginx's reverse proxy |
2577 | requires: |
2578 | db: |
2579 | interface: mysql |
2580 | + nfs: |
2581 | + interface: mount |
2582 | provides: |
2583 | website: |
2584 | interface: http |
2585 | +peers: |
2586 | + loadbalancer: |
2587 | + interface: reversenginx |
2588 | |
2589 | === modified file 'revision' |
2590 | --- revision 2012-06-18 20:28:16 +0000 |
2591 | +++ revision 2012-08-21 13:22:29 +0000 |
2592 | @@ -1,1 +1,5 @@ |
2593 | +<<<<<<< TREE |
2594 | 34 |
2595 | +======= |
2596 | +78 |
2597 | +>>>>>>> MERGE-SOURCE |
Looks sane to me.