Overview

Namespaces

  • OpenCloud
    • Autoscale
      • Resource
    • CloudMonitoring
      • Exception
      • Resource
    • Common
      • Collection
      • Constants
      • Exceptions
      • Http
        • Message
      • Log
      • Resource
      • Service
    • Compute
      • Constants
      • Exception
      • Resource
    • Database
      • Resource
    • DNS
      • Collection
      • Resource
    • Identity
      • Constants
      • Resource
    • Image
      • Enum
      • Resource
        • JsonPatch
        • Schema
    • LoadBalancer
      • Enum
      • Resource
    • ObjectStore
      • Constants
      • Exception
      • Resource
      • Upload
    • Orchestration
    • Queues
      • Exception
      • Resource
    • Volume
      • Resource
  • PHP

Classes

  • Flavor
  • Image
  • Network
  • Server
  • ServerMetadata
  • VolumeAttachment
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  1: <?php
  2: /**
  3:  * Copyright 2012-2014 Rackspace US, Inc.
  4:  *
  5:  * Licensed under the Apache License, Version 2.0 (the "License");
  6:  * you may not use this file except in compliance with the License.
  7:  * You may obtain a copy of the License at
  8:  *
  9:  * http://www.apache.org/licenses/LICENSE-2.0
 10:  *
 11:  * Unless required by applicable law or agreed to in writing, software
 12:  * distributed under the License is distributed on an "AS IS" BASIS,
 13:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14:  * See the License for the specific language governing permissions and
 15:  * limitations under the License.
 16:  */
 17: 
 18: namespace OpenCloud\Compute\Resource;
 19: 
 20: use OpenCloud\Common\Resource\NovaResource;
 21: use OpenCloud\DNS\Resource\HasPtrRecordsInterface;
 22: use OpenCloud\Image\Resource\ImageInterface;
 23: use OpenCloud\Volume\Resource\Volume;
 24: use OpenCloud\Common\Exceptions;
 25: use OpenCloud\Common\Http\Message\Formatter;
 26: use OpenCloud\Common\Lang;
 27: use OpenCloud\Compute\Constants\ServerState;
 28: use OpenCloud\Compute\Service;
 29: 
 30: /**
 31:  * A virtual machine (VM) instance in the Cloud Servers environment.
 32:  *
 33:  * @note This implementation supports extension attributes OS-DCF:diskConfig,
 34:  * RAX-SERVER:bandwidth, rax-bandwidth:bandwith.
 35:  */
 36: class Server extends NovaResource implements HasPtrRecordsInterface
 37: {
 38:     /**
 39:      * The server status. {@see \OpenCloud\Compute\Constants\ServerState} for supported types.
 40:      *
 41:      * @var string
 42:      */
 43:     public $status;
 44: 
 45:     /**
 46:      * @var string The time stamp for the last update.
 47:      */
 48:     public $updated;
 49: 
 50:     /**
 51:      * The compute provisioning algorithm has an anti-affinity property that
 52:      * attempts to spread customer VMs across hosts. Under certain situations,
 53:      * VMs from the same customer might be placed on the same host. $hostId
 54:      * represents the host your server runs on and can be used to determine this
 55:      * scenario if it is relevant to your application.
 56:      *
 57:      * @var string
 58:      */
 59:     public $hostId;
 60: 
 61:     /**
 62:      * @var type Public and private IP addresses for this server.
 63:      */
 64:     public $addresses;
 65: 
 66:     /**
 67:      * @var array Server links.
 68:      */
 69:     public $links;
 70: 
 71:     /**
 72:      * The Image for this server.
 73:      *
 74:      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Images-d1e4435.html
 75:      * @var ImageInterface
 76:      */
 77:     public $image;
 78: 
 79:     /**
 80:      * The Flavor for this server.
 81:      *
 82:      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Flavors-d1e4188.html
 83:      * @var type
 84:      */
 85:     public $flavor;
 86: 
 87:     /**
 88:      * @var type
 89:      */
 90:     public $networks = array();
 91: 
 92:     /**
 93:      * @var string The server ID.
 94:      */
 95:     public $id;
 96: 
 97:     /**
 98:      * @var string The user ID.
 99:      */
100:     public $user_id;
101: 
102:     /**
103:      * @var string The server name.
104:      */
105:     public $name;
106: 
107:     /**
108:      * @var string The time stamp for the creation date.
109:      */
110:     public $created;
111: 
112:     /**
113:      * @var string The tenant ID.
114:      */
115:     public $tenant_id;
116: 
117:     /**
118:      * @var string The public IP version 4 access address.
119:      */
120:     public $accessIPv4;
121: 
122:     /**
123:      * @var string The public IP version 6 access address.
124:      */
125:     public $accessIPv6;
126: 
127:     /**
128:      * The build completion progress, as a percentage. Value is from 0 to 100.
129:      * @var int
130:      */
131:     public $progress;
132: 
133:     /**
134:      * @var string The root password (only populated on server creation).
135:      */
136:     public $adminPass;
137: 
138:     /**
139:      * @var mixed Metadata key and value pairs.
140:      */
141:     public $metadata;
142: 
143:     protected static $json_name = 'server';
144:     protected static $url_resource = 'servers';
145: 
146:     /** @var string|object Keypair or string representation of keypair name */
147:     public $keypair;
148: 
149:     /**
150:      * @var array Uploaded file attachments
151:      */
152:     private $personality = array();
153: 
154:     /**
155:      * @var type Image reference (for create)
156:      */
157:     private $imageRef;
158: 
159:     /**
160:      * @var type Flavor reference (for create)
161:      */
162:     private $flavorRef;
163: 
164:     /**
165:      * Cloud-init boot executable code
166:      * @var string
167:      */
168:     public $user_data;
169: 
170:     /**
171:      * Creates a new Server object and associates it with a Compute service
172:      *
173:      * @param mixed $info
174:      *      * If NULL, an empty Server object is created
175:      *      * If an object, then a Server object is created from the data in the
176:      *      object
177:      *      * If a string, then it's treated as a Server ID and retrieved from the
178:      *      service
179:      *      The normal use case for SDK clients is to treat it as either NULL or an
180:      *      ID. The object value parameter is a special case used to construct
181:      *      a Server object from a ServerList element to avoid a secondary
182:      *      call to the Service.
183:      * @throws ServerNotFound if a 404 is returned
184:      * @throws UnknownError if another error status is reported
185:      */
186:     public function __construct(Service $service, $info = null)
187:     {
188:         // make the service persistent
189:         parent::__construct($service, $info);
190: 
191:         // the metadata item is an object, not an array
192:         $this->metadata = $this->metadata();
193:     }
194: 
195:     /**
196:      * Returns the primary external IP address of the server
197:      *
198:      * This function is based upon the accessIPv4 and accessIPv6 values.
199:      * By default, these are set to the public IP address of the server.
200:      * However, these values can be modified by the user; this might happen,
201:      * for example, if the server is behind a firewall and needs to be
202:      * routed through a NAT device to be reached.
203:      *
204:      * @api
205:      * @param integer $type the type of IP version (4 or 6) to return
206:      * @return string IP address
207:      */
208:     public function ip($type = null)
209:     {
210:         switch ($type) {
211:             default:
212:             case 4:
213:                 $value = $this->accessIPv4;
214:                 break;
215:             case 6:
216:                 $value = $this->accessIPv6;
217:                 break;
218:         }
219: 
220:         return $value;
221:     }
222: 
223:     /**
224:      * {@inheritDoc}
225:      */
226:     public function create($params = array())
227:     {
228:         $this->id = null;
229:         $this->status = null;
230: 
231:         if (isset($params['imageId'])) {
232:             $this->imageRef = $params['imageId'];
233:         }
234: 
235:         if (isset($params['flavorId'])) {
236:             $this->flavorRef = $params['flavorId'];
237:         }
238: 
239:         return parent::create($params);
240:     }
241: 
242:     /**
243:      * Rebuilds an existing server
244:      *
245:      * @api
246:      * @param array $params - an associative array of key/value pairs of
247:      *                      attributes to set on the new server
248:      */
249:     public function rebuild($params = array())
250:     {
251:         if (!isset($params['adminPass'])) {
252:             throw new Exceptions\RebuildError(
253:                 Lang::Translate('adminPass required when rebuilding server')
254:             );
255:         }
256: 
257:         if (!isset($params['image'])) {
258:             throw new Exceptions\RebuildError(
259:                 Lang::Translate('image required when rebuilding server')
260:             );
261:         }
262: 
263:         $object = (object) array(
264:             'rebuild' => (object) array(
265:                     'imageRef'  => $params['image']->id(),
266:                     'adminPass' => $params['adminPass'],
267:                     'name'      => (array_key_exists('name', $params) ? $params['name'] : $this->name)
268:                 )
269:         );
270: 
271:         return $this->action($object);
272:     }
273: 
274:     /**
275:      * Reboots a server
276:      *
277:      * A "soft" reboot requests that the operating system reboot itself; a "hard" reboot is the equivalent of pulling
278:      * the power plug and then turning it back on, with a possibility of data loss.
279:      *
280:      * @api
281:      * @param  string $type A particular reboot State. See Constants\ServerState for string values.
282:      * @return \Guzzle\Http\Message\Response
283:      */
284:     public function reboot($type = null)
285:     {
286:         if (!$type) {
287:             $type = ServerState::REBOOT_STATE_HARD;
288:         }
289: 
290:         $object = (object) array('reboot' => (object) array('type' => $type));
291: 
292:         return $this->action($object);
293:     }
294: 
295:     /**
296:      * Creates a new image from a server
297:      *
298:      * @api
299:      * @param string $name     The name of the new image
300:      * @param array  $metadata Optional metadata to be stored on the image
301:      * @return boolean|Image New Image instance on success; FALSE on failure
302:      * @throws Exceptions\ImageError
303:      */
304:     public function createImage($name, $metadata = array())
305:     {
306:         if (empty($name)) {
307:             throw new Exceptions\ImageError(
308:                 Lang::translate('Image name is required to create an image')
309:             );
310:         }
311: 
312:         // construct a createImage object for jsonization
313:         $object = (object) array('createImage' => (object) array(
314:                 'name'     => $name,
315:                 'metadata' => (object) $metadata
316:             ));
317: 
318:         $response = $this->action($object);
319: 
320:         if (!$response || !($location = $response->getHeader('Location'))) {
321:             return false;
322:         }
323: 
324:         return new Image($this->getService(), basename($location));
325:     }
326: 
327:     /**
328:      * Schedule daily image backups
329:      *
330:      * @api
331:      * @param mixed $retention - false (default) indicates you want to
332:      *                         retrieve the image schedule. $retention <= 0 indicates you
333:      *                         want to delete the current schedule. $retention > 0 indicates
334:      *                         you want to schedule image backups and you would like to
335:      *                         retain $retention backups.
336:      * @return mixed an object or FALSE on error
337:      * @throws Exceptions\ServerImageScheduleError if an error is encountered
338:      */
339:     public function imageSchedule($retention = false)
340:     {
341:         $url = $this->getUrl('rax-si-image-schedule');
342: 
343:         if ($retention === false) {
344:             // Get current retention
345:             $request = $this->getClient()->get($url);
346:         } elseif ($retention <= 0) {
347:             // Delete image schedule
348:             $request = $this->getClient()->delete($url);
349:         } else {
350:             // Set image schedule
351:             $object = (object) array('image_schedule' =>
352:                                         (object) array('retention' => $retention)
353:             );
354:             $body = json_encode($object);
355:             $request = $this->getClient()->post($url, self::getJsonHeader(), $body);
356:         }
357: 
358:         $body = Formatter::decode($request->send());
359: 
360:         return (isset($body->image_schedule)) ? $body->image_schedule : (object) array();
361:     }
362: 
363:     /**
364:      * Initiates the resize of a server
365:      *
366:      * @api
367:      * @param  Flavor  $flavorRef a Flavor object indicating the new server size
368:      * @return boolean TRUE on success; FALSE on failure
369:      */
370:     public function resize(Flavor $flavorRef)
371:     {
372:         // construct a resize object for jsonization
373:         $object = (object) array(
374:             'resize' => (object) array('flavorRef' => $flavorRef->id)
375:         );
376: 
377:         return $this->action($object);
378:     }
379: 
380:     /**
381:      * confirms the resize of a server
382:      *
383:      * @api
384:      * @return boolean TRUE on success; FALSE on failure
385:      */
386:     public function resizeConfirm()
387:     {
388:         $object = (object) array('confirmResize' => null);
389:         $response = $this->action($object);
390:         $this->refresh($this->id);
391: 
392:         return $response;
393:     }
394: 
395:     /**
396:      * reverts the resize of a server
397:      *
398:      * @api
399:      * @return boolean TRUE on success; FALSE on failure
400:      */
401:     public function resizeRevert()
402:     {
403:         $object = (object) array('revertResize' => null);
404: 
405:         return $this->action($object);
406:     }
407: 
408:     /**
409:      * Sets the root password on the server
410:      *
411:      * @api
412:      * @param  string  $newPassword The new root password for the server
413:      * @return boolean TRUE on success; FALSE on failure
414:      */
415:     public function setPassword($newPassword)
416:     {
417:         $object = (object) array(
418:             'changePassword' => (object) array('adminPass' => $newPassword)
419:         );
420: 
421:         return $this->action($object);
422:     }
423: 
424:     /**
425:      * Puts the server into *rescue* mode
426:      *
427:      * @api
428:      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/rescue_mode.html
429:      * @return string the root password of the rescue server
430:      * @throws Exceptions\ServerActionError if the server has no ID (i.e., has not
431:      *      been created yet)
432:      */
433:     public function rescue()
434:     {
435:         $this->checkExtension('os-rescue');
436: 
437:         if (empty($this->id)) {
438:             throw new Exceptions\ServerActionError(
439:                 Lang::translate('Server has no ID; cannot Rescue()')
440:             );
441:         }
442: 
443:         $data = (object) array('rescue' => 'none');
444: 
445:         $response = $this->action($data);
446:         $body = Formatter::decode($response);
447: 
448:         return (isset($body->adminPass)) ? $body->adminPass : false;
449:     }
450: 
451:     /**
452:      * Takes the server out of RESCUE mode
453:      *
454:      * @api
455:      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/rescue_mode.html
456:      * @return HttpResponse
457:      * @throws Exceptions\ServerActionError if the server has no ID (i.e., has not
458:      *      been created yet)
459:      */
460:     public function unrescue()
461:     {
462:         $this->checkExtension('os-rescue');
463: 
464:         if (!isset($this->id)) {
465:             throw new Exceptions\ServerActionError(Lang::translate('Server has no ID; cannot Unescue()'));
466:         }
467: 
468:         $object = (object) array('unrescue' => null);
469: 
470:         return $this->action($object);
471:     }
472: 
473:     /**
474:      * Retrieves the metadata associated with a Server.
475:      *
476:      * If a metadata item name is supplied, then only the single item is
477:      * returned. Otherwise, the default is to return all metadata associated
478:      * with a server.
479:      *
480:      * @api
481:      * @param string $key - the (optional) name of the metadata item to return
482:      * @return ServerMetadata object
483:      * @throws Exceptions\MetadataError
484:      */
485:     public function metadata($key = null)
486:     {
487:         return new ServerMetadata($this, $key);
488:     }
489: 
490:     /**
491:      * Returns the IP address block for the Server or for a specific network.
492:      *
493:      * @api
494:      * @param string $network - if supplied, then only the IP(s) for the
495:      *                        specified network are returned. Otherwise, all IPs are returned.
496:      * @return object
497:      * @throws Exceptions\ServerIpsError
498:      */
499:     public function ips($network = null)
500:     {
501:         $url = Lang::noslash($this->Url('ips/' . $network));
502: 
503:         $response = $this->getClient()->get($url)->send();
504:         $body = Formatter::decode($response);
505: 
506:         return (isset($body->addresses)) ? $body->addresses :
507:             ((isset($body->network)) ? $body->network : (object) array());
508:     }
509: 
510:     /**
511:      * Attaches a volume to a server
512:      *
513:      * Requires the os-volumes extension. This is a synonym for
514:      * `VolumeAttachment::create()`
515:      *
516:      * @api
517:      * @param OpenCloud\Volume\Resource\Volume $volume The volume to attach. If
518:      *                                                 "auto" is specified (the default), then the first available
519:      *                                                 device is used to mount the volume (for example, if the primary
520:      *                                                 disk is on `/dev/xvhda`, then the new volume would be attached
521:      *                                                 to `/dev/xvhdb`).
522:      * @param string                           $device the device to which to attach it
523:      */
524:     public function attachVolume(Volume $volume, $device = 'auto')
525:     {
526:         $this->checkExtension('os-volumes');
527: 
528:         return $this->volumeAttachment()->create(array(
529:             'volumeId' => $volume->id,
530:             'device'   => ($device == 'auto' ? null : $device)
531:         ));
532:     }
533: 
534:     /**
535:      * Removes a volume attachment from a server
536:      *
537:      * Requires the os-volumes extension. This is a synonym for
538:      * `VolumeAttachment::delete()`
539:      * @param OpenCloud\Volume\Resource\Volume $volume The volume to remove
540:      */
541:     public function detachVolume(Volume $volume)
542:     {
543:         $this->checkExtension('os-volumes');
544: 
545:         return $this->volumeAttachment($volume->id)->delete();
546:     }
547: 
548:     /**
549:      * Returns a VolumeAttachment object
550:      *
551:      */
552:     public function volumeAttachment($id = null)
553:     {
554:         $resource = new VolumeAttachment($this->getService());
555:         $resource->setParent($this)->populate($id);
556: 
557:         return $resource;
558:     }
559: 
560:     /**
561:      * Returns a Collection of VolumeAttachment objects
562:      * @return Collection
563:      */
564:     public function volumeAttachmentList()
565:     {
566:         return $this->getService()->collection(
567:             'OpenCloud\Compute\Resource\VolumeAttachment', null, $this
568:         );
569:     }
570: 
571:     /**
572:      * Adds a "personality" file to be uploaded during create() or rebuild()
573:      *
574:      * @api
575:      * @param string $path The path where the file will be stored on the
576:      *                     target server (up to 255 characters)
577:      * @param string $data the file contents (max size set by provider)
578:      * @return void
579:      */
580:     public function addFile($path, $data)
581:     {
582:         $this->personality[$path] = base64_encode($data);
583:     }
584: 
585:     /**
586:      * Returns a console connection
587:      * Note: Where is this documented?
588:      *
589:      * @codeCoverageIgnore
590:      */
591:     public function console($type = 'novnc')
592:     {
593:         $action = (strpos('spice', $type) !== false) ? 'os-getSPICEConsole' : 'os-getVNCConsole';
594:         $object = (object) array($action => (object) array('type' => $type));
595: 
596:         $response = $this->action($object);
597:         $body = Formatter::decode($response);
598: 
599:         return (isset($body->console)) ? $body->console : false;
600:     }
601: 
602:     protected function createJson()
603:     {
604:         // Convert some values
605:         $this->metadata->sdk = $this->getService()->getClient()->getUserAgent();
606: 
607:         if ($this->image instanceof ImageInterface) {
608:             $this->imageRef = $this->image->getId();
609:         }
610:         if ($this->flavor instanceof Flavor) {
611:             $this->flavorRef = $this->flavor->id;
612:         }
613: 
614:         // Base object
615:         $server = (object) array(
616:             'name'      => $this->name,
617:             'imageRef'  => $this->imageRef,
618:             'flavorRef' => $this->flavorRef
619:         );
620: 
621:         if ($this->metadata->count()) {
622:             $server->metadata = $this->metadata->toArray();
623:         }
624: 
625:         // Networks
626:         if (is_array($this->networks) && count($this->networks)) {
627: 
628:             $server->networks = array();
629: 
630:             foreach ($this->networks as $network) {
631:                 if (!$network instanceof Network) {
632:                     throw new Exceptions\InvalidParameterError(sprintf(
633:                         'When creating a server, the "networks" key must be an ' .
634:                         'array of OpenCloud\Compute\Network objects with valid ' .
635:                         'IDs; variable passed in was a [%s]',
636:                         gettype($network)
637:                     ));
638:                 }
639:                 if (empty($network->id)) {
640:                     $this->getLogger()->warning('When creating a server, the '
641:                         . 'network objects passed in must have an ID'
642:                     );
643:                     continue;
644:                 }
645:                 // Stock networks array
646:                 $server->networks[] = (object) array('uuid' => $network->id);
647:             }
648:         }
649: 
650:         // Personality files
651:         if (!empty($this->personality)) {
652:             $server->personality = array();
653:             foreach ($this->personality as $path => $data) {
654:                 // Stock personality array
655:                 $server->personality[] = (object) array(
656:                     'path'     => $path,
657:                     'contents' => $data
658:                 );
659:             }
660:         }
661: 
662:         // Keypairs
663:         if (!empty($this->keypair)) {
664:             if (is_string($this->keypair)) {
665:                 $server->key_name = $this->keypair;
666:             } elseif (isset($this->keypair['name']) && is_string($this->keypair['name'])) {
667:                 $server->key_name = $this->keypair['name'];
668:             } elseif ($this->keypair instanceof Keypair && $this->keypair->getName()) {
669:                 $server->key_name = $this->keypair->getName();
670:             }
671:         }
672: 
673:         // Cloud-init executable
674:         if (!empty($this->user_data)) {
675:             $server->user_data = $this->user_data;
676:         }
677: 
678:         return (object) array('server' => $server);
679:     }
680: 
681:     protected function updateJson($params = array())
682:     {
683:         return (object) array('server' => (object) $params);
684:     }
685: }
686: 
PHP OpenCloud API API documentation generated by ApiGen 2.8.0