Overview

Namespaces

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

Classes

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