Index: trunk/extensions/OpenStackManager/SpecialNovaInstance.php |
— | — | @@ -13,11 +13,11 @@ |
14 | 14 | |
15 | 15 | wfLoadExtensionMessages('OpenStackManager'); |
16 | 16 | $user = new OpenStackNovaUser(); |
17 | | - $project = $wgRequest->getVal('project'); |
18 | 17 | if ( ! $user->exists() ) { |
19 | 18 | $this->noCredentials(); |
20 | 19 | return true; |
21 | 20 | } |
| 21 | + $project = $wgRequest->getVal('project'); |
22 | 22 | $userCredentials = $user->getCredentials( $project ); |
23 | 23 | $this->userNova = new OpenStackNovaController( $userCredentials ); |
24 | 24 | $adminCredentials = $wgOpenStackManagerNovaAdminKeys; |
— | — | @@ -64,7 +64,7 @@ |
65 | 65 | $this->setHeaders(); |
66 | 66 | $wgOut->setPagetitle("Create Instance"); |
67 | 67 | |
68 | | - $instanceid = $wgRequest->getVal('instanceid'); |
| 68 | + $project = $wgRequest->getVal('project'); |
69 | 69 | |
70 | 70 | # TODO: Add project name field |
71 | 71 | |
— | — | @@ -131,11 +131,21 @@ |
132 | 132 | 'label-message' => 'keypair', |
133 | 133 | ); |
134 | 134 | |
| 135 | + $instanceInfo['action'] = array( |
| 136 | + 'type' => 'hidden', |
| 137 | + 'default' => 'create', |
| 138 | + ); |
| 139 | + |
| 140 | + $instanceInfo['project'] = array( |
| 141 | + 'type' => 'hidden', |
| 142 | + 'default' => htmlentities( $project ), |
| 143 | + ); |
| 144 | + |
135 | 145 | #TODO: Add availablity zone field |
136 | 146 | |
137 | | - $instanceForm = new OpenStackCreateInstanceForm( $instanceInfo, 'openstackmanager-form' ); |
138 | | - $instanceForm->setTitle( SpecialPage::getTitleFor( 'OpenStackCreateInstance' )); |
139 | | - $instanceForm->setSubmitID( 'openstackmanager-form-createinstancesubmit' ); |
| 147 | + $instanceForm = new OpenStackCreateInstanceForm( $instanceInfo, 'novainstance-form' ); |
| 148 | + $instanceForm->setTitle( SpecialPage::getTitleFor( 'NovaInstance' )); |
| 149 | + $instanceForm->setSubmitID( 'novainstance-form-createinstancesubmit' ); |
140 | 150 | $instanceForm->setSubmitCallback( array( $this, 'tryCreateSubmit' ) ); |
141 | 151 | $instanceForm->show(); |
142 | 152 | |
Index: trunk/extensions/OpenStackManager/OpenStackNovaUser.php |
— | — | @@ -48,7 +48,7 @@ |
49 | 49 | } |
50 | 50 | } |
51 | 51 | |
52 | | - function hasProjects() { |
| 52 | + function getProjects() { |
53 | 53 | global $wgAuth; |
54 | 54 | global $wgOpenStackManagerLDAPProjectBaseDN; |
55 | 55 | |
— | — | @@ -60,19 +60,21 @@ |
61 | 61 | $filter = "(&(projectManager=*)(member=$this->userDN))"; |
62 | 62 | $result = ldap_search( $wgAuth->ldapconn, $wgOpenStackManagerLDAPProjectBaseDN, $filter ); |
63 | 63 | if ( $result ) { |
64 | | - $entries = ldap_get_entries( $wgAuth->ldapconn, $entry ); |
| 64 | + $entries = ldap_get_entries( $wgAuth->ldapconn, $result ); |
65 | 65 | if ( $entries ) { |
66 | 66 | # First entry is always a count |
67 | 67 | array_shift($entries); |
68 | 68 | foreach ( $entries as $entry ) { |
69 | | - array_push( $projects, $entry['cn'] ); |
| 69 | + array_push( $projects, $entry['cn'][0] ); |
70 | 70 | } |
71 | 71 | } |
| 72 | + } else { |
| 73 | + $wgAuth->printDebug( "No result found when searching for user's projects", NONSENSITIVE ); |
72 | 74 | } |
73 | 75 | return $projects; |
74 | 76 | } |
75 | 77 | |
76 | | - function hasRoles( $project='' ) { |
| 78 | + function getRoles( $project='' ) { |
77 | 79 | # Currently unsupported |
78 | 80 | return array(); |
79 | 81 | } |
— | — | @@ -115,6 +117,24 @@ |
116 | 118 | $wgAuth->bindAs( $wgOpenStackManagerLDAPUser, $wgOpenStackManagerLDAPUserPassword ); |
117 | 119 | } |
118 | 120 | |
| 121 | + function importKeypair( $key ) { |
| 122 | + global $wgAuth; |
| 123 | + global $wgOpenStackManagerLDAPUser, $wgOpenStackManagerLDAPUserPassword; |
| 124 | + |
| 125 | + $wgAuth->connect(); |
| 126 | + $wgAuth->bindAs( $wgOpenStackManagerLDAPUser, $wgOpenStackManagerLDAPUserPassword ); |
| 127 | + |
| 128 | + $values['sshpublickey'] = $key; |
| 129 | + $success = @ldap_modify( $wgAuth->ldapconn, $this->userDN, $values ); |
| 130 | + if ( $success ) { |
| 131 | + $wgAuth->printDebug( "Successfully imported the user's sshpublickey", NONSENSITIVE ); |
| 132 | + return true; |
| 133 | + } else { |
| 134 | + $wgAuth->printDebug( "Failed to import the user's sshpublickey", NONSENSITIVE ); |
| 135 | + return false; |
| 136 | + } |
| 137 | + } |
| 138 | + |
119 | 139 | static function uuid4() { |
120 | 140 | uuid_create( &$uuid ); |
121 | 141 | uuid_make( $uuid, UUID_MAKE_V4 ); |
Index: trunk/extensions/OpenStackManager/SpecialNovaKey.php |
— | — | @@ -0,0 +1,164 @@ |
| 2 | +<?php |
| 3 | +class SpecialNovaKey extends SpecialPage { |
| 4 | + |
| 5 | + var $userNova, $userLDAP; |
| 6 | + |
| 7 | + function __construct() { |
| 8 | + parent::__construct( 'NovaKey' ); |
| 9 | + } |
| 10 | + |
| 11 | + function execute( $par ) { |
| 12 | + global $wgRequest; |
| 13 | + |
| 14 | + wfLoadExtensionMessages('OpenStackManager'); |
| 15 | + $this->userLDAP = new OpenStackNovaUser(); |
| 16 | + if ( ! $this->userLDAP->exists() ) { |
| 17 | + $this->noCredentials(); |
| 18 | + return true; |
| 19 | + } |
| 20 | + |
| 21 | + $project = $wgRequest->getVal('project'); |
| 22 | + $action = $wgRequest->getVal('action'); |
| 23 | + if ( $action == "import" ) { |
| 24 | + $this->importKey(); |
| 25 | + } else if ( $action == "delete" ) { |
| 26 | + if ( ! $this->userLDAP->inProject( $project ) ) { |
| 27 | + $this->notInProject(); |
| 28 | + return true; |
| 29 | + } |
| 30 | + $this->deleteKey(); |
| 31 | + } else { |
| 32 | + $this->listKeys(); |
| 33 | + } |
| 34 | + } |
| 35 | + |
| 36 | + function noCredentials() { |
| 37 | + global $wgOut; |
| 38 | + |
| 39 | + $this->setHeaders(); |
| 40 | + $wgOut->setPagetitle("No Nova credentials found for your account"); |
| 41 | + $wgOut->addHTML('<p>There were no Nova credentials found for your user account. Please ask a Nova administrator to create credentials for you.</p>'); |
| 42 | + } |
| 43 | + |
| 44 | + function notInProject() { |
| 45 | + global $wgOut; |
| 46 | + |
| 47 | + $this->setHeaders(); |
| 48 | + $wgOut->setPagetitle("Your account is not in the project requested"); |
| 49 | + $wgOut->addHTML('<p>You can not complete the action requested as your user account is not in the project requested.</p>'); |
| 50 | + } |
| 51 | + |
| 52 | + function importKey() { |
| 53 | + global $wgRequest, $wgOut; |
| 54 | + |
| 55 | + $project = $wgRequest->getVal('project'); |
| 56 | + if ( $project && ! $this->userLDAP->inProject( $project ) ) { |
| 57 | + $this->notInProject(); |
| 58 | + return true; |
| 59 | + } |
| 60 | + $userCredentials = $this->userLDAP->getCredentials( $project ); |
| 61 | + $this->userNova = new OpenStackNovaController( $userCredentials ); |
| 62 | + |
| 63 | + $this->setHeaders(); |
| 64 | + $wgOut->setPagetitle("Import Key"); |
| 65 | + |
| 66 | + # TODO: Add project name field |
| 67 | + |
| 68 | + $keyInfo = Array(); |
| 69 | + $keyInfo['keyName'] = array( |
| 70 | + 'type' => 'text', |
| 71 | + 'label-message' => 'keyname', |
| 72 | + 'default' => '', |
| 73 | + 'section' => 'key/info', |
| 74 | + ); |
| 75 | + |
| 76 | + $keyInfo['key'] = array( |
| 77 | + 'type' => 'textarea', |
| 78 | + 'section' => 'key/info', |
| 79 | + 'default' => '', |
| 80 | + 'label-message' => 'key', |
| 81 | + ); |
| 82 | + |
| 83 | + $keyInfo['action'] = array( |
| 84 | + 'type' => 'hidden', |
| 85 | + 'default' => 'import', |
| 86 | + ); |
| 87 | + |
| 88 | + $keyInfo['project'] = array( |
| 89 | + 'type' => 'hidden', |
| 90 | + 'default' => htmlentities( $project ), |
| 91 | + ); |
| 92 | + |
| 93 | + #TODO: Add availablity zone field |
| 94 | + |
| 95 | + $keyForm = new SpecialNovaKeyForm( $keyInfo, 'novakey-form' ); |
| 96 | + $keyForm->setTitle( SpecialPage::getTitleFor( 'NovaKey' )); |
| 97 | + $keyForm->setSubmitID( 'novakey-form-createkeysubmit' ); |
| 98 | + $keyForm->setSubmitCallback( array( $this, 'tryImportSubmit' ) ); |
| 99 | + $keyForm->show(); |
| 100 | + |
| 101 | + } |
| 102 | + |
| 103 | + function deleteKey() { |
| 104 | + global $wgOut; |
| 105 | + |
| 106 | + $project = $wgRequest->getVal('project'); |
| 107 | + if ( $project && ! $this->userLDAP->inProject( $project ) ) { |
| 108 | + $this->notInProject(); |
| 109 | + return true; |
| 110 | + } |
| 111 | + $this->setHeaders(); |
| 112 | + $wgOut->setPagetitle("Confirm key deletion"); |
| 113 | + return true; |
| 114 | + } |
| 115 | + |
| 116 | + function listKeys() { |
| 117 | + global $wgOut; |
| 118 | + |
| 119 | + $this->setHeaders(); |
| 120 | + $wgOut->setPagetitle("Key list"); |
| 121 | + |
| 122 | + $out = ''; |
| 123 | + $projects = $this->userLDAP->getProjects(); |
| 124 | + foreach( $projects as $project ) { |
| 125 | + $userCredentials = $this->userLDAP->getCredentials( $project ); |
| 126 | + $this->userNova = new OpenStackNovaController( $userCredentials ); |
| 127 | + $keypairs = $this->userNova->getKeypairs(); |
| 128 | + if ( ! $keypairs ) { |
| 129 | + continue; |
| 130 | + } |
| 131 | + $out .= Html::element( 'h2', array(), $project ); |
| 132 | + $projectOut = Html::element( 'th', array(), 'Name' ); |
| 133 | + $projectOut .= Html::element( 'th', array(), 'Fingerprint' ); |
| 134 | + foreach ( $keypairs as $keypair ) { |
| 135 | + $keyOut = Html::element( 'td', array(), $keypair->getKeyName() ); |
| 136 | + $keyOut .= Html::element( 'td', array(), $keypair->getKeyFingerprint() ); |
| 137 | + $projectOut .= Html::rawElement( 'tr', array(), $keyOut ); |
| 138 | + } |
| 139 | + $out .= Html::rawElement( 'table', array( 'id' => 'novainstancelist', 'class' => 'wikitable' ), $projectOut ); |
| 140 | + } |
| 141 | + |
| 142 | + $wgOut->addHTML( $out ); |
| 143 | + } |
| 144 | + |
| 145 | + function tryImportSubmit( $formData, $entryPoint = 'internal' ) { |
| 146 | + global $wgOut; |
| 147 | + |
| 148 | + $success = $this->userLDAP->importKeypair( $formData['key'] ); |
| 149 | + if ( ! $success ) { |
| 150 | + $out = Html::element( 'p', array(), 'Failed to import keypair' ); |
| 151 | + return false; |
| 152 | + } |
| 153 | + # OpenStack's EC2 API doesn't yet support importing keys |
| 154 | + //$keypair = $this->userNova->importKeypair( $formData['keyname'], $formData['key'] ); |
| 155 | + |
| 156 | + #$out = Html::element( 'p', array(), 'Imported keypair ' . $keypair->getKeyName() . ' with fingerprint ' . $keypair->getKeyFingerprint() ); |
| 157 | + $out = Html::element( 'p', array(), 'Imported keypair' ); |
| 158 | + |
| 159 | + $wgOut->addHTML( $out ); |
| 160 | + return true; |
| 161 | + } |
| 162 | +} |
| 163 | + |
| 164 | +class SpecialNovaKeyForm extends HTMLForm { |
| 165 | +} |
Index: trunk/extensions/OpenStackManager/OpenStackNovaController.php |
— | — | @@ -68,10 +68,12 @@ |
69 | 69 | function getKeypairs( $reload = false ) { |
70 | 70 | if ( count( $this->keypairs ) == 0 || $reload ) { |
71 | 71 | $this->keypairs = array(); |
72 | | - $keypairs = $this->novaConnection->describe_key_pairs(); |
73 | | - $keypairs = $keypairs->body->keypairsSet->item; |
| 72 | + $response = $this->novaConnection->describe_key_pairs(); |
| 73 | + $keypairs = $response->body->keypairsSet->item; |
74 | 74 | foreach ( $keypairs as $keypair ) { |
75 | | - $this->keypairs["$keypair->keyName"] = $keypair; |
| 75 | + $keypair = new OpenStackNovaKeypair( $keypair ); |
| 76 | + $keyname = $keypair->getKeyName(); |
| 77 | + $this->keypairs["$keyname"] = $keypair; |
76 | 78 | } |
77 | 79 | } |
78 | 80 | return $this->keypairs; |
— | — | @@ -94,7 +96,7 @@ |
95 | 97 | function createInstance( $image, $key, $instanceType, $availabilityZone ) { |
96 | 98 | # 1, 1 is min and max number of instances to create. |
97 | 99 | # We never want to make more than one at a time. |
98 | | - $instance = $this->novaConnection->run_instances($image, 1, 1, array( |
| 100 | + $response = $this->novaConnection->run_instances($image, 1, 1, array( |
99 | 101 | 'KeyName' => $key, |
100 | 102 | 'InstanceType' => $instanceType, |
101 | 103 | 'Placement.AvailabilityZone' => $availabilityZone, |
— | — | @@ -107,4 +109,14 @@ |
108 | 110 | return $instance; |
109 | 111 | } |
110 | 112 | |
| 113 | + function importKeyPair( $keyName, $key ) { |
| 114 | + $response = $this->novaConnection->import_key_pair( $keyName, $key ); |
| 115 | + |
| 116 | + $keypair = new OpenStackNovaKeypair( $response->body ); |
| 117 | + $keyName = $keypair->getKeyName(); |
| 118 | + $this->keypairs["$keyName"] = $keypair; |
| 119 | + |
| 120 | + return $keypair; |
| 121 | + } |
| 122 | + |
111 | 123 | } |
Index: trunk/extensions/OpenStackManager/OpenStackNovaKeypair.php |
— | — | @@ -0,0 +1,20 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +# TODO: Make this an abstract class, and make the EC2 API a subclass |
| 5 | +class OpenStackNovaKeyPair { |
| 6 | + |
| 7 | + var $keypair; |
| 8 | + |
| 9 | + function __construct( $apiKeypairResponse ) { |
| 10 | + $this->keypair = $apiKeypairResponse; |
| 11 | + } |
| 12 | + |
| 13 | + function getKeyName() { |
| 14 | + return $this->keypair->keyName; |
| 15 | + } |
| 16 | + |
| 17 | + function getKeyFingerprint() { |
| 18 | + return $this->keypair->keyFingerprint; |
| 19 | + } |
| 20 | + |
| 21 | +} |
Index: trunk/extensions/OpenStackManager/OpenStackManager.php |
— | — | @@ -36,11 +36,15 @@ |
37 | 37 | $wgExtensionMessagesFiles['OpenStackManager'] = $dir . 'OpenStackManager.i18n.php'; |
38 | 38 | $wgExtensionAliasesFiles['OpenStackManager'] = $dir . 'OpenStackManager.alias.php'; |
39 | 39 | $wgAutoloadClasses['OpenStackNovaInstance'] = $dir . 'OpenStackNovaInstance.php'; |
| 40 | +$wgAutoloadClasses['OpenStackNovaKeypair'] = $dir . 'OpenStackNovaKeypair.php'; |
40 | 41 | $wgAutoloadClasses['OpenStackNovaController'] = $dir . 'OpenStackNovaController.php'; |
41 | 42 | $wgAutoloadClasses['OpenStackNovaUser'] = $dir . 'OpenStackNovaUser.php'; |
42 | 43 | $wgAutoloadClasses['SpecialNovaInstance'] = $dir . 'SpecialNovaInstance.php'; |
| 44 | +$wgAutoloadClasses['SpecialNovaKey'] = $dir . 'SpecialNovaKey.php'; |
43 | 45 | $wgAutoloadClasses['AmazonEC2'] = $dir . 'aws-sdk/sdk.class.php'; |
44 | 46 | $wgSpecialPages['NovaInstance'] = 'SpecialNovaInstance'; |
45 | 47 | $wgSpecialPageGroups['NovaInstance'] = 'other'; |
| 48 | +$wgSpecialPages['NovaKey'] = 'SpecialNovaKey'; |
| 49 | +$wgSpecialPageGroups['NovaKey'] = 'other'; |
46 | 50 | |
47 | 51 | $wgHooks['LDAPSetCreationValues'][] = 'OpenStackNovaUser::LDAPSetCreationValues'; |