コード例 #1
0
ファイル: cloudcli.php プロジェクト: ndejong/cloudcli
        public function cmd_refresh() {
                $args = func_get_args();
                $this->Out->debug(__METHOD__,$args);

                // Define the meta for this command
                if(isset($args[0]) && $args[0] == '__meta') {
                        return array(
                            'command' => str_replace('cmd_','',__FUNCTION__),
                            'description' => 'Manually cause a refresh of all cloud resource data',
                            'sub_commands' => array()
                        );
                }

                // Update instances data
                $this->Cloud->refreshCloudData();

                $this->Out->msg();
        }
コード例 #2
0
ファイル: NdJCloudInstance.php プロジェクト: ndejong/cloudcli
        /**
         * instanceStart
         *
         * @param string $name
         * @param int $count
         */
        public function instanceStart($name,$count='1',$return_launch_spec_only=false) {
                $this->Out->debug(__METHOD__,func_get_args());

                // Update all data
                $this->Cloud->refreshCloudData();

                // Determine the ami platform
                $platform = $this->getAttribute($name,'platform','config');

                if(empty($platform)) {
                        try {
                                $response = $this->Cloud->EC2->describe_images(array(
                                    'ImageId' => $this->getAttribute($name,'imageId','config')
                                ));
                        } catch (RequestCore_Exception $e) {}
                        $platform = (string) $response->{'body'}->{'imagesSet'}->{'item'}->{'platform'};
                }

                if(empty($platform)) {
                        $this->Out->error("Unable to determine instance image platform.  Resolve this by adding a 'platform' configuration item to this instance definition.");
                        return false;
                }

                // The array of user data files
                $user_data_scripts = array();

                // Add the update_sources script first if required for this instance
                $update_platform = $this->getAttribute($name,'tagUpdatePlatform','config');
                if('true' == strtolower($update_platform) || '1' == $update_platform || 'yes' == strtolower($update_platform)) {
                        $user_data_scripts[] = $this->getScript('bootstrap/'.strtolower($platform).'/update-platform');
                }

                // Add dependancies as required
                $user_data_scripts[] = $this->getScript('bootstrap/'.strtolower($platform).'/install-dependencies');

                // Make sure this instance exists
                if(!in_array($name,$this->getNames('config'))) {
                        $this->Out->error('Unknown instance: '.$name);
                        return false;
                }

                // If address assigned check that it is available
                $address_id = $this->getAttribute($name,'address','config');
                if(!empty($address_id) && $this->Cloud->Address->getAttribute($address_id,'instanceId')) {
                        $this->Out->error('Required address '.$address_id.' is already in use by another instance');
                        return false;
                }

                // If volumes are assigned check they are all available
                $volumes = $this->getAttribute($name,'volumes','config');
                if(!empty($volumes)) {
                        foreach($volumes as $volume_id) {
                                if($this->Cloud->Volume->getAttribute($volume_id,'instanceId')) {
                                        $this->Out->error('Required volume '.$volume_id.' is already in use by another instance');
                                        return false;
                                }

                                // Establish scripts for volume mounts
                                $user_data_scripts[] = $this->getScript('bootstrap/common/mount-volume',$this->Cloud->Volume->getAttribute($volume_id,'device','config'),$this->Cloud->Volume->getAttribute($volume_id,'tagMount','config'));
                        }
                }

                // If there is a count value > 1 make sure we are not attempting to assocaite any volumes or addresses
                if($count > 1) {
                        if(!empty($address_id)) {
                                $this->Out->error('Cannot start multiple instances using the same address: '.$address_id);
                                return false;
                        }
                        if(!empty($volumes)) {
                                $this->Out->error('Cannot start multiple instances using the same volumes: '.join(',',$volumes));
                                return false;
                        }
                }

                // Establish the associated recipe scripts
                $recipes = $this->getAttribute($name,'tagRecipes','config');
                if(!empty($recipes)) {
                        foreach($recipes as $recipe) {
                                
                                $script = $this->getScript('recipes/'.strtolower($platform).'/'.$recipe);
                                if(empty($script)) {
                                    
                                        $script = $this->getScript(strtolower($platform).'/'.$recipe);
                                        if(empty($script)) {
                                            
                                                $script = $this->getScript($recipe);
                                                if(empty($script)) {
                                                        $this->Out->error('Unable to locate recipe for: '.$recipe);
                                                        return false;
                                                }
                                        }
                                }
                                $user_data_scripts[] = $script;
                        }
                }

                // Add our own package install scripts
                $packages = $this->getAttribute($name,'tagPackages','config');
                if(!empty($packages)) {
                        foreach($packages as $package_name) {

                                // Confirm the package name
                                $timestamp_revision = null;
                                if(preg_match("/^(.*?)-(\d\d\d\d\d\d\d\d-\d\d\d\d\d\d)/",$package_name,$matches)) {
                                        $package_name = $matches[1];
                                        $timestamp_revision = $matches[2];
                                }

                                $user_data_scripts[] = $this->Cloud->Package->getInstallScript($package_name,$timestamp_revision);
                        }
                }

                // instance_id
                $instance_ids = array();

                // Make sure ec2-run-instances is installed here
                $ec2_run_instances = $this->Cloud->SystemCommand->exec('which ec2-run-instances');
                if($ec2_run_instances && isset($this->Cloud->config['aws']['private_key_file']) && isset($this->Cloud->config['aws']['certificate_file']) && !empty($this->Cloud->config['aws']['private_key_file']) && !empty($this->Cloud->config['aws']['certificate_file']) ) {

                        // Make sure private_key_file and certificate_key_file are present
                        $certificate_file = $this->Cloud->config['aws']['certificate_file'];
                        $certificate_file = str_replace('~',getenv('HOME'),$certificate_file);
                        if(!is_file($certificate_file)) {
                                $this->Out->error('Unable to locate certificate_file: '.$certificate_file);
                                return false;
                        }
                        $this->Out->msg('Using certificate_file: '.$certificate_file);

                        $private_key_file = $this->Cloud->config['aws']['private_key_file'];
                        $private_key_file = str_replace('~',getenv('HOME'),$private_key_file);
                        if(!is_file($private_key_file)) {
                                $this->Out->error('Unable to locate private_key_file: '.$private_key_file);
                                return false;
                        }
                        $this->Out->msg('Using private_key_file: '.$private_key_file);

                        // API target URL
                        $this->Out->msg('API target: '.$this->Cloud->EC2->hostname);
                        
                        $cmd = 'ec2-run-instances '.$this->getAttribute($name,'imageId','config');
                        $cmd .= ' --cert '.$certificate_file;
                        $cmd .= ' --private-key '.$private_key_file;
                        $cmd .= ' --url '.$this->Cloud->EC2->hostname;
                        $cmd .= ' --user-data-file '.$this->doPackageUserDataScripts($user_data_scripts,true);
                        $cmd .= ' --region '.$this->Cloud->config['ec2']['region'];
                        $cmd .= ' --instance-type '.$this->getAttribute($name,'instanceType','config');
                        $cmd .= ' --instance-count '.$count;
                        //$cmd .= ' --ramdisk '; // do we really care about this?  NdJ

                        if($this->getAttribute($name,'keyName','config')) {
                                $cmd .= ' --key '.$this->getAttribute($name,'keyName','config');
                        }

                        if($this->getAttribute($name,'availabilityZone','config')) {
                                $cmd .= ' --availability-zone '.$this->getAttribute($name,'availabilityZone','config');
                        }

                        if($this->getAttribute($name,'kernelId','config')) {
                                $cmd .= ' --kernel '.$this->getAttribute($name,'kernelId','config');
                        }

                        foreach($this->getAttribute($name,'groups','config') as $group) {
                                $cmd .= ' --group '.$group;
                        }
                        //$this->Out->error($cmd);

                        $this->Out->msg('Starting instance(s) using ec2-run-instances',false);
                        $response = $this->Cloud->SystemCommand->exec($cmd);
                        //$this->Out->error($cmd);
                        preg_match_all("/INSTANCE\s+(i-.+?)\s+ami/",$response,$matches);
                        if(!isset($matches[1][0])) {
                                $this->Out->error('Unable to start instance(s) using ec2-run-instances');
                                return false;
                        }
                        $this->Out->msg(' - done');

                        $instance_ids = $matches[1];
                } else {
                        $this->Out->msg('Starting '.$name.' using AWS SDK for PHP');

                        $config = array();
                        
                        # KeyName
                        if($this->getAttribute($name,'keyName','config')) { $config['KeyName'] = $this->getAttribute($name,'keyName','config'); }

                        # SecurityGroup
                        if($this->getAttribute($name,'groups','config')) { $config['SecurityGroup'] = $this->getAttribute($name,'groups','config'); }

                        # UserData
                        $config['UserData'] = base64_encode(file_get_contents($this->doPackageUserDataScripts($user_data_scripts,true,true)));

                        # InstanceType
                        if($this->getAttribute($name,'instanceType','config')) { $config['InstanceType'] = $this->getAttribute($name,'instanceType','config'); }

                        # AvailabilityZone
                        if($this->getAttribute($name,'availabilityZone','config')) { $config['Placement'] = array('AvailabilityZone'=>$this->getAttribute($name,'availabilityZone','config')); }

                        # KernelId
                        if($this->getAttribute($name,'kernelId','config')) { $config['KernelId'] = $this->getAttribute($name,'kernelId','config'); }
						
						// exit here to return this LaunchSpecification only
						if($return_launch_spec_only) {
							$config['ImageId'] = $this->getAttribute($name,'imageId','config');
							return array($config);
						}

                        //print_r($config);exit;

                        try {
                                $response = $this->Cloud->EC2->run_instances(
                                        $this->getAttribute($name,'imageId','config'),
                                        $count,$count,$config
                                );
                        } catch (RequestCore_Exception $e) {}

                        if(!$response->isOK()) {
                                $this->Out->error('Unable to start instances - check if '.$this->getAttribute($name,'imageId','config').' is available in '.$this->Cloud->config['ec2']['region']);
                                if(isset($e)) { $this->Out->error($e); }
                                $this->Out->error(print_r($response,1));
                                return false;
                        }

                        foreach($response->{'body'}->{'instancesSet'}->{'item'} as $item) {
                                $instance_ids[] = (string) $item->{'instanceId'};
                        }
                }

                // Make sure we received at least one instance_id
                if(empty($instance_ids)) {
                        $this->Out->error('No instance started!');
                        return false;
                }

                $blocked = true;
                while($blocked) {

                        // Ensure we have up-to-date instance data
                        $this->getData(null,true);
                        
                        $data = null;
                        foreach($instance_ids as $instance_id) {

                                $state = $this->getAttribute($instance_id,'state','cloud');

                                if('running'==$state) {
                                        $this->Out->msg('Instance running: '.$instance_id);

                                        // Set all the tags for this instance
                                        $this->syncTags($name,$instance_id,array('tagName','tagRecipes','tagPackages','tagUpdatePlatform','tagUsername'));

                                        // Associate address
                                        if(!empty($address_id)) {
                                                if(!$this->Cloud->Address->addressAssociate($address_id,$instance_id)) {
                                                        return false;
                                                }
                                        }

                                        // Attach volumes to this instance
                                        if(!empty($volumes)) {
                                                foreach($volumes as $volume_id) {
                                                        if(!$this->Cloud->Volume->volumeMount($volume_id,$instance_id,false)) {
                                                                return false;
                                                        }
                                                }
                                        }

                                        $instance_ids = $this->removeElementFromArray($instance_id,$instance_ids);
                                }
                        }

                        if(count($instance_ids) == 0) {
                                $blocked = false;
                        } else {
                                sleep(10);
                        }
                }

                // Ensure we have up-to-date instance data
                $this->getData(null,true);
        }