1: <?php
2:
3: namespace Saklient\Cloud\Resources;
4:
5: require_once __DIR__ . "/../../../Saklient/Errors/HttpException.php";
6: use \Saklient\Errors\HttpException;
7: require_once __DIR__ . "/../../../Saklient/Errors/SaklientException.php";
8: use \Saklient\Errors\SaklientException;
9: require_once __DIR__ . "/../../../Saklient/Cloud/Client.php";
10: use \Saklient\Cloud\Client;
11: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/Resource.php";
12: use \Saklient\Cloud\Resources\Resource;
13: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/Icon.php";
14: use \Saklient\Cloud\Resources\Icon;
15: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/Disk.php";
16: use \Saklient\Cloud\Resources\Disk;
17: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/Iface.php";
18: use \Saklient\Cloud\Resources\Iface;
19: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/ServerPlan.php";
20: use \Saklient\Cloud\Resources\ServerPlan;
21: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/ServerInstance.php";
22: use \Saklient\Cloud\Resources\ServerInstance;
23: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/IsoImage.php";
24: use \Saklient\Cloud\Resources\IsoImage;
25: require_once __DIR__ . "/../../../Saklient/Cloud/Resources/ServerActivity.php";
26: use \Saklient\Cloud\Resources\ServerActivity;
27: require_once __DIR__ . "/../../../Saklient/Cloud/Enums/EServerInstanceStatus.php";
28: use \Saklient\Cloud\Enums\EServerInstanceStatus;
29: require_once __DIR__ . "/../../../Saklient/Cloud/Enums/EAvailability.php";
30: use \Saklient\Cloud\Enums\EAvailability;
31: require_once __DIR__ . "/../../../Saklient/Cloud/Models/Model_Disk.php";
32: use \Saklient\Cloud\Models\Model_Disk;
33: require_once __DIR__ . "/../../../Saklient/Cloud/Models/Model_Iface.php";
34: use \Saklient\Cloud\Models\Model_Iface;
35: require_once __DIR__ . "/../../../Saklient/Util.php";
36: use \Saklient\Util;
37:
38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51:
52: class Server extends Resource {
53:
54: 55: 56: 57: 58: 59: 60:
61: protected $m_id;
62:
63: 64: 65: 66: 67: 68: 69:
70: protected $m_name;
71:
72: 73: 74: 75: 76: 77: 78:
79: protected $m_description;
80:
81: 82: 83: 84: 85: 86: 87:
88: protected $m_tags;
89:
90: 91: 92: 93: 94: 95: 96:
97: protected $m_icon;
98:
99: 100: 101: 102: 103: 104: 105:
106: protected $m_plan;
107:
108: 109: 110: 111: 112: 113: 114:
115: protected $m_ifaces;
116:
117: 118: 119: 120: 121: 122: 123:
124: protected $m_instance;
125:
126: 127: 128: 129: 130: 131: 132:
133: protected $m_availability;
134:
135: 136: 137: 138: 139: 140:
141: protected function _apiPath()
142: {
143: return "/server";
144: }
145:
146: 147: 148: 149: 150: 151:
152: protected function _rootKey()
153: {
154: return "Server";
155: }
156:
157: 158: 159: 160: 161: 162:
163: protected function _rootKeyM()
164: {
165: return "Servers";
166: }
167:
168: 169: 170: 171: 172: 173:
174: public function _className()
175: {
176: return "Server";
177: }
178:
179: 180: 181: 182: 183: 184:
185: public function _id()
186: {
187: return $this->get_id();
188: }
189:
190: 191: 192: 193: 194: 195:
196: public function save()
197: {
198: return $this->_save();
199: }
200:
201: 202: 203: 204: 205: 206:
207: public function reload()
208: {
209: return $this->_reload();
210: }
211:
212: 213: 214: 215: 216: 217:
218: protected $_activity;
219:
220: 221: 222: 223: 224:
225: public function get_activity()
226: {
227: return $this->_activity;
228: }
229:
230:
231:
232: 233: 234: 235: 236: 237: 238:
239: public function __construct(\Saklient\Cloud\Client $client, $obj, $wrapped=false)
240: {
241: parent::__construct($client);
242: Util::validateArgCount(func_num_args(), 2);
243: Util::validateType($client, "\\Saklient\\Cloud\\Client");
244: Util::validateType($wrapped, "boolean");
245: $this->_activity = new ServerActivity($client);
246: $this->apiDeserialize($obj, $wrapped);
247: }
248:
249: 250: 251: 252: 253: 254: 255: 256:
257: protected function _onAfterApiDeserialize($r, $root)
258: {
259: Util::validateArgCount(func_num_args(), 2);
260: if ($r != null) {
261: $this->_activity->setSourceId($this->_id());
262: }
263: }
264:
265: 266: 267: 268: 269: 270:
271: public function isUp()
272: {
273: return $this->get_instance()->isUp();
274: }
275:
276: 277: 278: 279: 280: 281:
282: public function isDown()
283: {
284: return $this->get_instance()->isDown();
285: }
286:
287: 288: 289: 290: 291: 292:
293: public function boot()
294: {
295: $this->_client->request("PUT", $this->_apiPath() . "/" . Util::urlEncode($this->_id()) . "/power");
296: return $this->reload();
297: }
298:
299: 300: 301: 302: 303: 304:
305: public function shutdown()
306: {
307: $this->_client->request("DELETE", $this->_apiPath() . "/" . Util::urlEncode($this->_id()) . "/power");
308: return $this->reload();
309: }
310:
311: 312: 313: 314: 315: 316:
317: public function stop()
318: {
319: $this->_client->request("DELETE", $this->_apiPath() . "/" . Util::urlEncode($this->_id()) . "/power", (object)['Force' => true]);
320: return $this->reload();
321: }
322:
323: 324: 325: 326: 327: 328:
329: public function reboot()
330: {
331: $this->_client->request("PUT", $this->_apiPath() . "/" . Util::urlEncode($this->_id()) . "/reset");
332: return $this->reload();
333: }
334:
335: 336: 337: 338: 339: 340: 341:
342: public function sleepUntilUp($timeoutSec=180)
343: {
344: Util::validateType($timeoutSec, "int");
345: return $this->sleepUntil(EServerInstanceStatus::up, $timeoutSec);
346: }
347:
348: 349: 350: 351: 352: 353: 354:
355: public function sleepUntilDown($timeoutSec=180)
356: {
357: Util::validateType($timeoutSec, "int");
358: return $this->sleepUntil(EServerInstanceStatus::down, $timeoutSec);
359: }
360:
361: 362: 363: 364: 365: 366: 367: 368: 369:
370: private function sleepUntil($status, $timeoutSec=180)
371: {
372: Util::validateArgCount(func_num_args(), 1);
373: Util::validateType($status, "string");
374: Util::validateType($timeoutSec, "int");
375: $step = 10;
376: while (0 < $timeoutSec) {
377: try {
378: $this->reload();
379: }
380: catch (HttpException $ex) {
381: }
382: $s = null;
383: $inst = $this->instance;
384: if ($inst != null) {
385: $s = $inst->status;
386: }
387: if ($s == null) {
388: $s = EServerInstanceStatus::down;
389: }
390: if ($s == $status) {
391: return true;
392: }
393: $timeoutSec -= $step;
394: if (0 < $timeoutSec) {
395: Util::sleep($step);
396: }
397: }
398: return false;
399: }
400:
401: 402: 403: 404: 405: 406: 407: 408: 409:
410: public function changePlan(\Saklient\Cloud\Resources\ServerPlan $planTo)
411: {
412: Util::validateArgCount(func_num_args(), 1);
413: Util::validateType($planTo, "\\Saklient\\Cloud\\Resources\\ServerPlan");
414: $path = $this->_apiPath() . "/" . Util::urlEncode($this->_id()) . "/to/plan/" . Util::urlEncode($planTo->_id());
415: $result = $this->_client->request("PUT", $path);
416: $this->apiDeserialize($result, true);
417: return $this;
418: }
419:
420: 421: 422: 423: 424: 425:
426: public function findDisks()
427: {
428: $model = Util::createClassInstance("saklient.cloud.models.Model_Disk", new \ArrayObject([$this->_client]));
429: return $model->withServerId($this->_id())->find();
430: }
431:
432: 433: 434: 435: 436: 437:
438: public function addIface()
439: {
440: $model = Util::createClassInstance("saklient.cloud.models.Model_Iface", new \ArrayObject([$this->_client]));
441: $res = $model->create();
442: $res->serverId = $this->_id();
443: return $res->save();
444: }
445:
446: 447: 448: 449: 450: 451: 452:
453: public function insertIsoImage(\Saklient\Cloud\Resources\IsoImage $iso)
454: {
455: Util::validateArgCount(func_num_args(), 1);
456: Util::validateType($iso, "\\Saklient\\Cloud\\Resources\\IsoImage");
457: $path = $this->_apiPath() . "/" . Util::urlEncode($this->_id()) . "/cdrom";
458: $q = (object)['CDROM' => (object)['ID' => $iso->_id()]];
459: $this->_client->request("PUT", $path, $q);
460: $this->reload();
461: return $this;
462: }
463:
464: 465: 466: 467: 468: 469:
470: public function ejectIsoImage()
471: {
472: $path = $this->_apiPath() . "/" . Util::urlEncode($this->_id()) . "/cdrom";
473: $this->_client->request("DELETE", $path);
474: $this->reload();
475: return $this;
476: }
477:
478: 479: 480: 481: 482:
483: private $n_id = false;
484:
485: 486: 487: 488: 489: 490: 491:
492: private function get_id()
493: {
494: return $this->m_id;
495: }
496:
497:
498:
499: 500: 501: 502: 503:
504: private $n_name = false;
505:
506: 507: 508: 509: 510: 511: 512:
513: private function get_name()
514: {
515: return $this->m_name;
516: }
517:
518: 519: 520: 521: 522: 523: 524: 525:
526: private function set_name($v)
527: {
528: Util::validateArgCount(func_num_args(), 1);
529: Util::validateType($v, "string");
530: $this->m_name = $v;
531: $this->n_name = true;
532: return $this->m_name;
533: }
534:
535:
536:
537: 538: 539: 540: 541:
542: private $n_description = false;
543:
544: 545: 546: 547: 548: 549: 550:
551: private function get_description()
552: {
553: return $this->m_description;
554: }
555:
556: 557: 558: 559: 560: 561: 562: 563:
564: private function set_description($v)
565: {
566: Util::validateArgCount(func_num_args(), 1);
567: Util::validateType($v, "string");
568: $this->m_description = $v;
569: $this->n_description = true;
570: return $this->m_description;
571: }
572:
573:
574:
575: 576: 577: 578: 579:
580: private $n_tags = false;
581:
582: 583: 584: 585: 586: 587: 588:
589: private function get_tags()
590: {
591: $this->n_tags = true;
592: return $this->m_tags;
593: }
594:
595: 596: 597: 598: 599: 600: 601: 602:
603: private function set_tags($v)
604: {
605: Util::validateArgCount(func_num_args(), 1);
606: Util::validateType($v, "\\ArrayObject");
607: if (is_array($v)) $v = Client::array2ArrayObject($v);
608: $this->m_tags = $v;
609: $this->n_tags = true;
610: return $this->m_tags;
611: }
612:
613:
614:
615: 616: 617: 618: 619:
620: private $n_icon = false;
621:
622: 623: 624: 625: 626: 627: 628:
629: private function get_icon()
630: {
631: return $this->m_icon;
632: }
633:
634: 635: 636: 637: 638: 639: 640: 641:
642: private function set_icon(\Saklient\Cloud\Resources\Icon $v=null)
643: {
644: Util::validateArgCount(func_num_args(), 1);
645: Util::validateType($v, "\\Saklient\\Cloud\\Resources\\Icon");
646: $this->m_icon = $v;
647: $this->n_icon = true;
648: return $this->m_icon;
649: }
650:
651:
652:
653: 654: 655: 656: 657:
658: private $n_plan = false;
659:
660: 661: 662: 663: 664: 665: 666:
667: private function get_plan()
668: {
669: return $this->m_plan;
670: }
671:
672: 673: 674: 675: 676: 677: 678: 679:
680: private function set_plan(\Saklient\Cloud\Resources\ServerPlan $v)
681: {
682: Util::validateArgCount(func_num_args(), 1);
683: Util::validateType($v, "\\Saklient\\Cloud\\Resources\\ServerPlan");
684: if (!$this->isNew) {
685: throw new SaklientException("immutable_field", "Immutable fields cannot be modified after the resource creation: " . "Saklient\\Cloud\\Resources\\Server#plan");
686: }
687: $this->m_plan = $v;
688: $this->n_plan = true;
689: return $this->m_plan;
690: }
691:
692:
693:
694: 695: 696: 697: 698:
699: private $n_ifaces = false;
700:
701: 702: 703: 704: 705: 706: 707:
708: private function get_ifaces()
709: {
710: return $this->m_ifaces;
711: }
712:
713:
714:
715: 716: 717: 718: 719:
720: private $n_instance = false;
721:
722: 723: 724: 725: 726: 727: 728:
729: private function get_instance()
730: {
731: return $this->m_instance;
732: }
733:
734:
735:
736: 737: 738: 739: 740:
741: private $n_availability = false;
742:
743: 744: 745: 746: 747: 748: 749:
750: private function get_availability()
751: {
752: return $this->m_availability;
753: }
754:
755:
756:
757: 758: 759: 760: 761: 762: 763:
764: protected function apiDeserializeImpl($r)
765: {
766: Util::validateArgCount(func_num_args(), 1);
767: $this->isNew = $r == null;
768: if ($this->isNew) {
769: $r = (object)[];
770: }
771: $this->isIncomplete = false;
772: if (Util::existsPath($r, "ID")) {
773: $this->m_id = Util::getByPath($r, "ID") == null ? null : "" . Util::getByPath($r, "ID");
774: }
775: else {
776: $this->m_id = null;
777: $this->isIncomplete = true;
778: }
779: $this->n_id = false;
780: if (Util::existsPath($r, "Name")) {
781: $this->m_name = Util::getByPath($r, "Name") == null ? null : "" . Util::getByPath($r, "Name");
782: }
783: else {
784: $this->m_name = null;
785: $this->isIncomplete = true;
786: }
787: $this->n_name = false;
788: if (Util::existsPath($r, "Description")) {
789: $this->m_description = Util::getByPath($r, "Description") == null ? null : "" . Util::getByPath($r, "Description");
790: }
791: else {
792: $this->m_description = null;
793: $this->isIncomplete = true;
794: }
795: $this->n_description = false;
796: if (Util::existsPath($r, "Tags")) {
797: if (Util::getByPath($r, "Tags") == null) {
798: $this->m_tags = new \ArrayObject([]);
799: }
800: else {
801: $this->m_tags = new \ArrayObject([]);
802: foreach (Util::getByPath($r, "Tags") as $t) {
803: $v1 = null;
804: $v1 = $t == null ? null : "" . $t;
805: $this->m_tags->append($v1);
806: }
807: }
808: }
809: else {
810: $this->m_tags = null;
811: $this->isIncomplete = true;
812: }
813: $this->n_tags = false;
814: if (Util::existsPath($r, "Icon")) {
815: $this->m_icon = Util::getByPath($r, "Icon") == null ? null : new Icon($this->_client, Util::getByPath($r, "Icon"));
816: }
817: else {
818: $this->m_icon = null;
819: $this->isIncomplete = true;
820: }
821: $this->n_icon = false;
822: if (Util::existsPath($r, "ServerPlan")) {
823: $this->m_plan = Util::getByPath($r, "ServerPlan") == null ? null : new ServerPlan($this->_client, Util::getByPath($r, "ServerPlan"));
824: }
825: else {
826: $this->m_plan = null;
827: $this->isIncomplete = true;
828: }
829: $this->n_plan = false;
830: if (Util::existsPath($r, "Interfaces")) {
831: if (Util::getByPath($r, "Interfaces") == null) {
832: $this->m_ifaces = new \ArrayObject([]);
833: }
834: else {
835: $this->m_ifaces = new \ArrayObject([]);
836: foreach (Util::getByPath($r, "Interfaces") as $t) {
837: $v2 = null;
838: $v2 = $t == null ? null : new Iface($this->_client, $t);
839: $this->m_ifaces->append($v2);
840: }
841: }
842: }
843: else {
844: $this->m_ifaces = null;
845: $this->isIncomplete = true;
846: }
847: $this->n_ifaces = false;
848: if (Util::existsPath($r, "Instance")) {
849: $this->m_instance = Util::getByPath($r, "Instance") == null ? null : new ServerInstance($this->_client, Util::getByPath($r, "Instance"));
850: }
851: else {
852: $this->m_instance = null;
853: $this->isIncomplete = true;
854: }
855: $this->n_instance = false;
856: if (Util::existsPath($r, "Availability")) {
857: $this->m_availability = Util::getByPath($r, "Availability") == null ? null : "" . Util::getByPath($r, "Availability");
858: }
859: else {
860: $this->m_availability = null;
861: $this->isIncomplete = true;
862: }
863: $this->n_availability = false;
864: }
865:
866: 867: 868: 869: 870: 871:
872: protected function apiSerializeImpl($withClean=false)
873: {
874: Util::validateType($withClean, "boolean");
875: $missing = new \ArrayObject([]);
876: $ret = (object)[];
877: if ($withClean || $this->n_id) {
878: Util::setByPath($ret, "ID", $this->m_id);
879: }
880: if ($withClean || $this->n_name) {
881: Util::setByPath($ret, "Name", $this->m_name);
882: }
883: else {
884: if ($this->isNew) {
885: $missing->append("name");
886: }
887: }
888: if ($withClean || $this->n_description) {
889: Util::setByPath($ret, "Description", $this->m_description);
890: }
891: if ($withClean || $this->n_tags) {
892: Util::setByPath($ret, "Tags", new \ArrayObject([]));
893: foreach ($this->m_tags as $r1) {
894: $v = null;
895: $v = $r1;
896: $ret->{"Tags"}->append($v);
897: }
898: }
899: if ($withClean || $this->n_icon) {
900: Util::setByPath($ret, "Icon", $withClean ? ($this->m_icon == null ? null : $this->m_icon->apiSerialize($withClean)) : ($this->m_icon == null ? (object)['ID' => "0"] : $this->m_icon->apiSerializeID()));
901: }
902: if ($withClean || $this->n_plan) {
903: Util::setByPath($ret, "ServerPlan", $withClean ? ($this->m_plan == null ? null : $this->m_plan->apiSerialize($withClean)) : ($this->m_plan == null ? (object)['ID' => "0"] : $this->m_plan->apiSerializeID()));
904: }
905: else {
906: if ($this->isNew) {
907: $missing->append("plan");
908: }
909: }
910: if ($withClean || $this->n_ifaces) {
911: Util::setByPath($ret, "Interfaces", new \ArrayObject([]));
912: foreach ($this->m_ifaces as $r2) {
913: $v = null;
914: $v = $withClean ? ($r2 == null ? null : $r2->apiSerialize($withClean)) : ($r2 == null ? (object)['ID' => "0"] : $r2->apiSerializeID());
915: $ret->{"Interfaces"}->append($v);
916: }
917: }
918: if ($withClean || $this->n_instance) {
919: Util::setByPath($ret, "Instance", $withClean ? ($this->m_instance == null ? null : $this->m_instance->apiSerialize($withClean)) : ($this->m_instance == null ? (object)['ID' => "0"] : $this->m_instance->apiSerializeID()));
920: }
921: if ($withClean || $this->n_availability) {
922: Util::setByPath($ret, "Availability", $this->m_availability);
923: }
924: if ($missing->count() > 0) {
925: throw new SaklientException("required_field", "Required fields must be set before the Server creation: " . implode(", ", (array)($missing)));
926: }
927: return $ret;
928: }
929:
930: 931: 932:
933: public function __get($key) {
934: switch ($key) {
935: case "activity": return $this->get_activity();
936: case "id": return $this->get_id();
937: case "name": return $this->get_name();
938: case "description": return $this->get_description();
939: case "tags": return $this->get_tags();
940: case "icon": return $this->get_icon();
941: case "plan": return $this->get_plan();
942: case "ifaces": return $this->get_ifaces();
943: case "instance": return $this->get_instance();
944: case "availability": return $this->get_availability();
945: default: return parent::__get($key);
946: }
947: }
948:
949: 950: 951:
952: public function __set($key, $v) {
953: switch ($key) {
954: case "name": return $this->set_name($v);
955: case "description": return $this->set_description($v);
956: case "tags": return $this->set_tags($v);
957: case "icon": return $this->set_icon($v);
958: case "plan": return $this->set_plan($v);
959: default: return parent::__set($key, $v);
960: }
961: }
962:
963: }
964:
965: