1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
17:
18: namespace OpenCloud\LoadBalancer\Resource;
19:
20: use OpenCloud\Common\Exceptions;
21: use OpenCloud\Common\Resource\PersistentResource;
22: use OpenCloud\DNS\Resource\HasPtrRecordsInterface;
23: use OpenCloud\LoadBalancer\Enum\NodeCondition;
24: use OpenCloud\LoadBalancer\Enum\IpType;
25: use OpenCloud\LoadBalancer\Enum\NodeType;
26:
27: 28: 29: 30: 31:
32: class LoadBalancer extends PersistentResource implements HasPtrRecordsInterface
33: {
34: public $id;
35:
36: 37: 38: 39: 40: 41:
42: public $name;
43:
44: 45: 46: 47: 48:
49: public $port;
50:
51: 52: 53: 54: 55:
56: public $protocol;
57:
58: 59: 60: 61: 62:
63: public $virtualIps = array();
64:
65: 66: 67: 68: 69:
70: public $nodes = array();
71:
72: 73: 74: 75: 76: 77:
78: public $accessList;
79:
80: 81: 82: 83: 84:
85: public $algorithm;
86:
87: 88: 89: 90: 91:
92: public $connectionLogging;
93:
94: 95: 96: 97: 98: 99:
100: public $connectionThrottle;
101:
102: 103: 104: 105: 106: 107:
108: public $healthMonitor;
109:
110: 111: 112: 113: 114: 115:
116: public $sessionPersistence;
117:
118: 119: 120: 121: 122: 123:
124: public $metadata = array();
125:
126: 127: 128: 129: 130: 131:
132: public $timeout;
133:
134: public $created;
135: public $updated;
136: public $status;
137: public $nodeCount;
138: public $sourceAddresses;
139: public $cluster;
140:
141: protected static $json_name = 'loadBalancer';
142: protected static $url_resource = 'loadbalancers';
143:
144: protected $associatedResources = array(
145: 'node' => 'Node',
146: 'virtualIp' => 'VirtualIp',
147: 'connectionLogging' => 'ConnectionLogging',
148: 'healthMonitor' => 'HealthMonitor',
149: 'sessionPersistance' => 'SessionPersistance'
150: );
151:
152: protected $associatedCollections = array(
153: 'nodes' => 'Node',
154: 'virtualIps' => 'VirtualIp',
155: 'accessList' => 'Access'
156: );
157:
158: protected $createKeys = array(
159: 'name',
160: 'port',
161: 'protocol',
162: 'virtualIps',
163: 'nodes',
164: 'accessList',
165: 'algorithm',
166: 'connectionLogging',
167: 'connectionThrottle',
168: 'healthMonitor',
169: 'sessionPersistence'
170: );
171:
172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189:
190: public function addNode(
191: $address,
192: $port,
193: $condition = NodeCondition::ENABLED,
194: $type = null,
195: $weight = null
196: ) {
197: $allowedConditions = array(
198: NodeCondition::ENABLED,
199: NodeCondition::DISABLED,
200: NodeCondition::DRAINING
201: );
202:
203: if (!in_array($condition, $allowedConditions)) {
204: throw new \InvalidArgumentException(sprintf(
205: "Invalid condition. It must one of the following: %s",
206: implode(', ', $allowedConditions)
207: ));
208: }
209:
210: $allowedTypes = array(NodeType::PRIMARY, NodeType::SECONDARY);
211: if ($type && !in_array($type, $allowedTypes)) {
212: throw new \InvalidArgumentException(sprintf(
213: "Invalid type. It must one of the following: %s",
214: implode(', ', $allowedTypes)
215: ));
216: }
217:
218: if ($weight && !is_numeric($weight)) {
219: throw new \InvalidArgumentException('Invalid weight. You must supply a numeric type');
220: }
221:
222:
223: $this->nodes[] = $this->node(array(
224: 'address' => $address,
225: 'port' => $port,
226: 'condition' => $condition,
227: 'type' => $type,
228: 'weight' => $weight
229: ));
230: }
231:
232: 233: 234: 235: 236: 237:
238: public function addNodes()
239: {
240: if (empty($this->nodes)) {
241: throw new Exceptions\MissingValueError(
242: 'Cannot add nodes; no nodes are defined'
243: );
244: }
245:
246: $requests = array();
247:
248: foreach ($this->nodes as $node) {
249: $requests[] = $this->getClient()->post($node->getUrl(), self::getJsonHeader(), $node->createJson());
250: }
251:
252: return $this->getClient()->send($requests);
253: }
254:
255: 256: 257: 258: 259: 260:
261: public function removeNode($nodeId)
262: {
263: return $this->node($nodeId)->delete();
264: }
265:
266: 267: 268: 269: 270: 271: 272: 273: 274: 275:
276: public function addVirtualIp($type = IpType::PUBLIC_TYPE, $ipVersion = null)
277: {
278: $object = new \stdClass();
279:
280: switch (strtoupper($type)) {
281: case IpType::PUBLIC_TYPE:
282: case IpType::SERVICENET_TYPE:
283: $object->type = strtoupper($type);
284: break;
285: default:
286: $object->id = $type;
287: break;
288: }
289:
290: if ($ipVersion) {
291: switch ($ipVersion) {
292: case 4:
293: $object->ipVersion = IpType::IPv4;
294: break;
295: case 6:
296: $object->ipVersion = IpType::IPv6;
297: break;
298: default:
299: throw new Exceptions\DomainError(sprintf(
300: 'Value [%s] for ipVersion is not valid',
301: $ipVersion
302: ));
303: }
304: }
305:
306: 307: 308: 309: 310:
311: if ($this->Id()) {
312: $virtualIp = $this->virtualIp();
313: $virtualIp->type = $type;
314: $virtualIp->ipVersion = $object->ipVersion;
315: return $virtualIp->create();
316: } else {
317:
318: $this->virtualIps[] = $object;
319: }
320:
321: return true;
322: }
323:
324: 325: 326: 327: 328:
329: public function node($id = null)
330: {
331: return $this->getService()->resource('Node', $id, $this);
332: }
333:
334: 335: 336: 337: 338:
339: public function nodeList()
340: {
341: return $this->getService()->resourceList('Node', null, $this);
342: }
343:
344: 345: 346: 347: 348:
349: public function nodeEvent()
350: {
351: return $this->getService()->resource('NodeEvent', null, $this);
352: }
353:
354: 355: 356: 357: 358:
359: public function nodeEventList()
360: {
361: return $this->getService()->resourceList('NodeEvent', null, $this);
362: }
363:
364: 365: 366: 367: 368:
369: public function virtualIp($data = null)
370: {
371: return $this->getService()->resource('VirtualIp', $data, $this);
372: }
373:
374: 375: 376:
377: public function virtualIpList()
378: {
379: return $this->getService()->resourceList('VirtualIp', null, $this);
380: }
381:
382: 383: 384: 385: 386:
387: public function sessionPersistence()
388: {
389: return $this->getService()->resource('SessionPersistence', null, $this);
390: }
391:
392: 393: 394: 395: 396:
397: public function errorPage()
398: {
399: return $this->getService()->resource('ErrorPage', null, $this);
400: }
401:
402: 403: 404: 405: 406:
407: public function healthMonitor()
408: {
409: return $this->getService()->resource('HealthMonitor', null, $this);
410: }
411:
412: 413: 414: 415: 416:
417: public function stats()
418: {
419: return $this->getService()->resource('Stats', null, $this);
420: }
421:
422: 423: 424:
425: public function usage()
426: {
427: return $this->getService()->resourceList('UsageRecord', null, $this);
428: }
429:
430: 431: 432: 433: 434:
435: public function access($data = null)
436: {
437: return $this->getService()->resource('Access', $data, $this);
438: }
439:
440: 441: 442: 443: 444: 445: 446: 447: 448: 449:
450: public function createAccessList(array $list)
451: {
452: $url = $this->getUrl();
453: $url->addPath('accesslist');
454:
455: $json = json_encode($list);
456: $this->checkJsonError();
457:
458: return $this->getClient()->post($url, self::getJsonHeader(), $json)->send();
459: }
460:
461: 462: 463:
464: public function accessList()
465: {
466: return $this->getService()->resourceList('Access', null, $this);
467: }
468:
469: 470: 471: 472: 473:
474: public function connectionThrottle()
475: {
476: return $this->getService()->resource('ConnectionThrottle', null, $this);
477: }
478:
479: 480: 481: 482: 483:
484: public function hasConnectionLogging()
485: {
486: $url = clone $this->getUrl();
487: $url->addPath('connectionlogging');
488:
489: $response = $this->getClient()->get($url)->send()->json();
490:
491: return isset($response['connectionLogging']['enabled'])
492: && $response['connectionLogging']['enabled'] === true;
493: }
494:
495: 496: 497: 498: 499: 500:
501: public function enableConnectionLogging($bool)
502: {
503: $url = clone $this->getUrl();
504: $url->addPath('connectionlogging');
505:
506: $body = array('connectionLogging' => (bool) $bool);
507:
508: return $this->getClient()->put($url, self::getJsonHeader(), $body)->send();
509: }
510:
511: 512: 513:
514: public function connectionLogging()
515: {
516: $this->getLogger()->deprecated(__METHOD__, 'hasConnectionLogging or enableConnectionLogging');
517: }
518:
519: 520: 521: 522: 523:
524: public function hasContentCaching()
525: {
526: $url = clone $this->getUrl();
527: $url->addPath('contentcaching');
528:
529: $response = $this->getClient()->get($url)->send()->json();
530:
531: return isset($response['contentCaching']['enabled'])
532: && $response['contentCaching']['enabled'] === true;
533: }
534:
535: 536: 537: 538: 539: 540:
541: public function enableContentCaching($bool)
542: {
543: $url = clone $this->getUrl();
544: $url->addPath('contentcaching');
545:
546: $body = array('contentCaching' => array('enabled' => (bool) $bool));
547: $body = json_encode($body);
548: $this->checkJsonError();
549:
550: return $this->getClient()->put($url, self::getJsonHeader(), $body)->send();
551: }
552:
553: 554: 555:
556: public function contentCaching()
557: {
558: $this->getLogger()->deprecated(__METHOD__, 'hasContentCaching or setContentCaching');
559: }
560:
561: 562: 563: 564: 565:
566: public function SSLTermination()
567: {
568: return $this->getService()->resource('SSLTermination', null, $this);
569: }
570:
571: 572: 573: 574: 575:
576: public function metadata($data = null)
577: {
578: return $this->getService()->resource('Metadata', $data, $this);
579: }
580:
581: 582: 583: 584: 585:
586: public function metadataList()
587: {
588: return $this->getService()->resourceList('Metadata', null, $this);
589: }
590:
591: protected function createJson()
592: {
593: $element = (object) array();
594:
595: foreach ($this->createKeys as $key) {
596: if ($key == 'nodes') {
597: foreach ($this->nodes as $node) {
598: $nodeObject = (object) array();
599: foreach ($node->createKeys as $key) {
600: if (!empty($node->$key)) {
601: $nodeObject->$key = $node->$key;
602: }
603: }
604: $element->nodes[] = (object) $nodeObject;
605: }
606: } elseif ($key == 'virtualIps') {
607: foreach ($this->virtualIps as $virtualIp) {
608: $element->virtualIps[] = $virtualIp;
609: }
610: } elseif (isset($this->$key)) {
611: $element->$key = $this->$key;
612: }
613: }
614:
615: $object = (object) array($this->jsonName() => $element);
616:
617: return $object;
618: }
619:
620: protected function updateJson($params = array())
621: {
622: $updatableFields = array('name', 'algorithm', 'protocol', 'port', 'timeout', 'halfClosed');
623:
624: $fields = array_keys($params);
625: foreach ($fields as $field) {
626: if (!in_array($field, $updatableFields)) {
627: throw new Exceptions\InvalidArgumentError("You cannot update $field.");
628: }
629: }
630:
631: $object = new \stdClass();
632: $object->loadBalancer = new \stdClass();
633: foreach ($params as $name => $value) {
634: $object->loadBalancer->$name = $this->$name;
635: }
636:
637: return $object;
638: }
639: }
640: