/**
  * Execute the job. Add an IP address to a DNS record when it is available
  * on the instance. If the instance does not exist, or it has not been
  * assigned an IP address, re-add the job.
  *
  * Upon successfully adding the host, this job will also add an Article for the
  * instance.
  *
  * @return bool
  */
 public function run()
 {
     global $wgOpenStackManagerNovaAdminKeys;
     global $wgAuth;
     $instanceid = $this->params['instanceid'];
     $wgAuth->printDebug("Running DNS job for {$instanceid}", NONSENSITIVE);
     $adminCredentials = $wgOpenStackManagerNovaAdminKeys;
     $adminNova = new OpenStackNovaController($adminCredentials);
     $instance = $adminNova->getInstance($instanceid);
     if (!$instance) {
         $wgAuth->printDebug("Instance doesn't exist for {$instanceid}", NONSENSITIVE);
         # Instance no longer exists
         return true;
     }
     $ip = $instance->getInstancePrivateIP();
     if (trim($ip) == '') {
         # IP hasn't been assigned yet
         # re-add to queue
         $wgAuth->printDebug("Readding job for {$instanceid}", NONSENSITIVE);
         $job = new OpenStackNovaHostJob($this->title, $this->params);
         $job->insert();
         return true;
     }
     $host = OpenStackNovaHost::getHostByInstanceId($instanceid);
     if (!$host) {
         $wgAuth->printDebug("Host record doesn't exist for {$instanceid}", NONSENSITIVE);
         return true;
     }
     $host->setARecord($ip);
     $instance->editArticle();
     return true;
 }
	/**
	 * @param  $apiInstanceResponse
	 * @param bool $loadhost, optional
	 */
	function __construct( $apiInstanceResponse, $loadhost = false ) {
		$this->instance = $apiInstanceResponse;
		if ( $loadhost ) {
			$this->host = OpenStackNovaHost::getHostByInstanceId( $this->getInstanceId() );
		} else {
			$this->host = null;
		}
	}
 public function execute()
 {
     if (!class_exists('EchoEvent')) {
         $this->error("Couldn't find EchoEvent class.\n", true);
     } elseif (!OpenStackNovaHost::validateHostname($this->getOption('instance'))) {
         $this->error("Instance hostname is invalid.\n", true);
     }
     $validActions = array('reboot', 'build');
     if (!in_array($this->getOption('action'), $validActions)) {
         $this->error("Unrecognised action.\n", true);
     }
     $dbw = wfGetDB(DB_MASTER);
     $result = $dbw->selectRow('openstack_notification_event', array('event_actor_id', 'event_project', 'event_instance_name'), array('event_action' => $this->getOption('action'), 'event_instance_host' => $this->getOption('instance')), __METHOD__);
     if (!$result) {
         $this->error("Lookup of temporary event info failed.\n", true);
     }
     $successful = EchoEvent::create(array('type' => 'osm-instance-' . $this->getOption('action') . '-completed', 'title' => Title::newFromText($result->event_project, NS_NOVA_RESOURCE), 'agent' => User::newFromId($result->event_actor_id), 'extra' => array('instanceName' => $result->event_instance_name, 'projectName' => $result->event_project, 'notifyAgent' => true)));
     if ($successful) {
         $dbw->delete('openstack_notification_event', array('event_action' => $this->getOption('action'), 'event_instance_host' => $this->getOption('instance'), 'event_instance_name' => $result->event_instance_name, 'event_project' => $result->event_project, 'event_actor_id' => $result->event_actor_id), __METHOD__);
         $this->output("Event created successfully.\n");
     } else {
         $this->error("Something went wrong creating the echo notification.\n", true);
     }
 }
 /**
  * @param  $formData
  * @param string $entryPoint
  * @return bool
  */
 function tryDeleteSubmit($formData, $entryPoint = 'internal')
 {
     $instance = $this->adminNova->getInstance($formData['instanceid']);
     if (!$instance) {
         $this->getOutput()->addWikiMsg('openstackmanager-nonexistanthost');
         return true;
     }
     $instancename = $instance->getInstanceName();
     $instanceid = $instance->getInstanceId();
     $success = $this->userNova->terminateInstance($instanceid);
     if ($success) {
         $instance->deleteArticle();
         $success = OpenStackNovaHost::deleteHostByInstanceId($instanceid);
         if ($success) {
             $this->getOutput()->addWikiMsg('openstackmanager-deletedinstance', $instanceid);
         } else {
             $this->getOutput()->addWikiMsg('openstackmanager-deletedinstance-faileddns', $instancename, $instanceid);
         }
     } else {
         $this->getOutput()->addWikiMsg('openstackmanager-deleteinstancefailed');
     }
     $out = '<br />';
     $out .= Linker::link($this->getTitle(), wfMsgHtml('openstackmanager-backinstancelist'));
     $this->getOutput()->addHTML($out);
     return true;
 }
 /**
  * Handle ?action=configure
  * @return bool
  */
 function configureInstance()
 {
     global $wgOpenStackManagerPuppetOptions;
     $this->setHeaders();
     $region = $this->getRequest()->getText('region');
     $instanceosid = $this->getRequest()->getText('instanceid');
     $instance = $this->userNova->getInstance($instanceosid);
     if (!$instance) {
         $this->getOutput()->addWikiMsg('openstackmanager-nonexistentresource');
         return false;
     }
     $project = $instance->getProject();
     if (!$this->userLDAP->inRole('projectadmin', $project)) {
         $this->notInRole('projectadmin', $project);
         return false;
     }
     $instanceid = $instance->getInstanceId();
     $instancename = $instance->getInstanceName();
     $this->getOutput()->setPagetitle($this->msg('openstackmanager-configureinstance', $instanceid, $instancename));
     $instanceInfo = array();
     $instanceInfo['instanceid'] = array('type' => 'hidden', 'default' => $instanceosid, 'name' => 'instanceid');
     $instanceInfo['project'] = array('type' => 'hidden', 'default' => $project, 'name' => 'project');
     $instanceInfo['region'] = array('type' => 'hidden', 'default' => $region, 'name' => 'region');
     if ($wgOpenStackManagerPuppetOptions['enabled']) {
         $host = OpenStackNovaHost::getHostByNameAndProject($instancename, $project, $region);
         if (!$host) {
             $this->getOutput()->addWikiMsg('openstackmanager-nonexistenthost');
             return false;
         }
         $puppetinfo = $host->getPuppetConfiguration();
         $this->setPuppetInfo($instanceInfo, $puppetinfo);
     }
     $instanceInfo['action'] = array('type' => 'hidden', 'default' => 'configure', 'name' => 'action');
     $instanceForm = new HTMLForm($instanceInfo, $this->getContext(), 'openstackmanager-novainstance');
     $instanceForm->setSubmitID('novainstance-form-configureinstancesubmit');
     $instanceForm->setSubmitCallback(array($this, 'tryConfigureSubmit'));
     $instanceForm->show();
     return true;
 }
 /**
  * Adds a host entry based on the hostname, IP addrss, and a domain. Returns null
  * if the entry already exists, or if the additional fails. This function should be used
  * for adding public DNS entries.
  *
  * @static
  * @param  $hostname
  * @param  $ip
  * @param  $domain OpenStackNovaDomain
  * @return bool|null|OpenStackNovaHost
  */
 static function addPublicHost($hostname, $ip, $domain)
 {
     global $wgAuth;
     global $wgOpenStackManagerLDAPInstanceBaseDN;
     OpenStackNovaLdapConnection::connect();
     $domainname = $domain->getFullyQualifiedDomainName();
     $host = OpenStackNovaHost::getHostByPublicIP($ip);
     if ($host) {
         $wgAuth->printDebug("Failed to add public host {$hostname} as the DNS entry already exists", NONSENSITIVE);
         return null;
     }
     $hostEntry = array();
     $hostEntry['objectclass'][] = 'dcobject';
     $hostEntry['objectclass'][] = 'dnsdomain';
     $hostEntry['objectclass'][] = 'domainrelatedobject';
     $hostEntry['dc'] = $ip;
     $hostEntry['arecord'] = $ip;
     $hostEntry['associateddomain'][] = $hostname . '.' . $domainname;
     $dn = 'dc=' . $ip . ',' . $wgOpenStackManagerLDAPInstanceBaseDN;
     $success = LdapAuthenticationPlugin::ldap_add($wgAuth->ldapconn, $dn, $hostEntry);
     if ($success) {
         $domain->updateSOA();
         $wgAuth->printDebug("Successfully added public host {$hostname}", NONSENSITIVE);
         return new OpenStackNovaHost(false, null, $ip);
     } else {
         $wgAuth->printDebug("Failed to add public host {$hostname} with dn = {$dn}", NONSENSITIVE);
         return null;
     }
 }
 /**
  * @param  $formData
  * @param string $entryPoint
  * @return bool
  */
 function tryCreateSubmit($formData, $entryPoint = 'internal')
 {
     global $wgOpenStackManagerProxyGateways;
     $goback = '<br />';
     $goback .= Linker::link($this->getPageTitle(), $this->msg('openstackmanager-backproxylist')->escaped());
     $project = $formData['project'];
     $backendPort = $formData['backendport'];
     $backendHost = $formData['backendhost'];
     $region = $formData['region'];
     $proxyName = $formData['proxyname'];
     $proxyDomain = $formData['domain'];
     $outputPage = $this->getOutput();
     $gatewayIP = $wgOpenStackManagerProxyGateways[$region];
     if (!array_key_exists($region, $wgOpenStackManagerProxyGateways)) {
         $outputPage->addWikiMsg('openstackmanager-addhostfailed', $proxyName, $gatewayIP);
         $outputPage->addHTML($goback);
         return true;
     }
     $domain = OpenStackNovaDomain::getDomainByName($proxyDomain);
     $gatewayhostbyip = OpenStackNovaHost::getHostByPublicIP($gatewayIP);
     $fqdn = $proxyName . '.' . $domain->getFullyQualifiedDomainName();
     $dnsSuccess = $this->addHost($proxyName, $proxyDomain, $gatewayIP);
     if ($dnsSuccess) {
         $outputPage->addWikiMsg('openstackmanager-addedhost', $proxyName, $gatewayIP);
     } else {
         $outputPage->addWikiMsg('openstackmanager-addhostfailed', $proxyName, $gatewayIP);
         $outputPage->addHTML($goback);
         return true;
     }
     # DNS looks good, now we can set up the proxy.
     $newProxy = $this->userNova->createProxy($fqdn, $backendHost, $backendPort);
     if ($newProxy) {
         $outputPage->addWikiMsg('openstackmanager-createdproxy', $fqdn, $backendHost . ":" . $backendPort);
     } else {
         $outputPage->addWikiMsg('openstackmanager-createproxyfailed', $fqdn);
         $this->deleteHost($fqdn, $gatewayIP);
         $outputPage->addHTML($goback);
         return true;
     }
     $outputPage->addHTML($goback);
     return true;
 }
	/**
	 * @param $formData
	 * @param string $entryPoint
	 * @return bool
	 */
	function tryRemoveHostSubmit( $formData, $entryPoint = 'internal' ) {
		$ip = $formData['ip'];
		$project = $formData['project'];
		$address = $this->adminNova->getAddress( $ip );
		$outputPage = $this->getOutput();
		if ( ! $address ) {
			$outputPage->addWikiMsg( 'openstackmanager-invalidaddress', $ip );
			return true;
		}
		if ( $address->getProject() != $project ) {
			$outputPage->addWikiMsg( 'openstackmanager-invalidaddressforproject', $ip );
			return true;
		}
		$hostname = $formData['hostname'];
		$domain = $formData['domain'];
		$domain = OpenStackNovaDomain::getDomainByName( $domain );
		$host = OpenStackNovaHost::getHostByName( $hostname, $domain );
		if ( $host ) {
			$fqdn = $hostname . '.' . $domain->getFullyQualifiedDomainName();
			$records = $host->getAssociatedDomains();
			if ( count( $records ) > 1 ) {
				# We need to keep the host, but remove the fqdn
				$success = $host->deleteAssociatedDomain( $fqdn );
				if ( $success ) {
					$outputPage->addWikiMsg( 'openstackmanager-removedhost', $hostname, $ip );
				} else {
					$outputPage->addWikiMsg( 'openstackmanager-removehostfailed', $ip, $hostname );
				}
			} else {
				# We need to remove the host entry
				$success = OpenStackNovaHost::deleteHost( $hostname, $domain );
				if ( $success ) {
					$outputPage->addWikiMsg( 'openstackmanager-removedhost', $hostname, $ip );
				} else {
					$outputPage->addWikiMsg( 'openstackmanager-removehostfailed', $ip, $hostname );
				}
			}
		} else {
			$outputPage->addWikiMsg( 'openstackmanager-nonexistenthost' );
		}
		$out = '<br />';
		$out .= Linker::link( $this->getTitle(), wfMsgHtml( 'openstackmanager-backaddresslist' ) );
		$outputPage->addHTML( $out );
		return true;
	}
 function loadHost()
 {
     $this->host = OpenStackNovaHost::getHostByNameAndProject($this->getInstanceName(), $this->getProject(), $this->region);
 }
 /**
  * @param $formData
  * @param string $entryPoint
  * @return bool
  */
 function tryRemoveHostSubmit($formData, $entryPoint = 'internal')
 {
     $id = $formData['id'];
     $address = $this->userNova->getAddress($id);
     $outputPage = $this->getOutput();
     if (!$address) {
         $outputPage->addWikiMsg('openstackmanager-invalidaddress', $id);
         return true;
     }
     $ip = $address->getPublicIp();
     $hostname = $formData['hostname'];
     $fqdn = $formData['fqdn'];
     $host = OpenStackNovaHost::getHostByPublicIP($ip);
     if ($host) {
         $records = $host->getAssociatedDomains();
         if (count($records) > 1) {
             # We need to keep the host, but remove the fqdn
             $success = $host->deleteAssociatedDomain($fqdn);
             if ($success) {
                 $outputPage->addWikiMsg('openstackmanager-removedhost', $hostname, $ip);
             } else {
                 $outputPage->addWikiMsg('openstackmanager-removehostfailed', $ip, $hostname);
             }
         } else {
             # We need to remove the host entry
             $success = $host->deleteHost();
             if ($success) {
                 $outputPage->addWikiMsg('openstackmanager-removedhost', $hostname, $ip);
             } else {
                 $outputPage->addWikiMsg('openstackmanager-removehostfailed', $ip, $hostname);
             }
         }
     } else {
         $outputPage->addWikiMsg('openstackmanager-nonexistenthost');
     }
     $out = '<br />';
     $out .= Linker::link($this->getPageTitle(), $this->msg('openstackmanager-backaddresslist')->escaped());
     $outputPage->addHTML($out);
     return true;
 }
 public function execute()
 {
     global $wgAuth;
     global $wgOpenStackManagerLDAPUsername;
     global $wgOpenStackManagerLDAPUserPassword;
     if ($this->hasOption('all-instances')) {
         if ($this->hasOption('region')) {
             $this->error("--all-instances cannot be used with --region.\n", true);
         }
         $instancelist = array();
         $user = new OpenStackNovaUser($wgOpenStackManagerLDAPUsername);
         $userNova = OpenStackNovaController::newFromUser($user);
         $projects = OpenStackNovaProject::getAllProjects();
         $userNova->setProject('bastion');
         $userNova->authenticate($wgOpenStackManagerLDAPUsername, $wgOpenStackManagerLDAPUserPassword);
         $regions = $userNova->getRegions('compute');
         foreach ($regions as $region) {
             foreach ($projects as $project) {
                 $projectName = $project->getProjectName();
                 $userNova->setProject($projectName);
                 $userNova->setRegion($region);
                 $instances = $userNova->getInstances();
                 if ($instances) {
                     foreach ($instances as $instance) {
                         $instancelist[] = array($region, $instance->getInstanceName(), $projectName);
                     }
                 }
             }
         }
     } elseif ($this->hasOption('name')) {
         if (!$this->hasOption('region')) {
             $this->error("--name requires --region.\n", true);
         }
         if (!$this->hasOption('project')) {
             $this->error("--name requires --project.\n", true);
         }
         $instancelist = array(array($this->getOption('region'), $this->getOption('name'), $this->getOption('project')));
     } else {
         $this->error("Must specify either --name or --all-instances.\n", true);
     }
     if (!class_exists('OpenStackNovaHost')) {
         $this->error("Couldn't find OpenStackNovaHost class.\n", true);
     }
     OpenStackNovaLdapConnection::connect();
     foreach ($instancelist as $instancepair) {
         list($instanceregion, $instancename, $instanceproject) = $instancepair;
         $host = OpenStackNovaHost::getHostByNameAndProject($instancename, $instanceproject, $instanceregion);
         if (!$host) {
             print "Skipping {$instancename}.{$instanceproject}.{$instanceregion}; not found.\n";
             continue;
         }
         print "\nFor instance {$instancename} in region {$instanceregion} and project {$instanceproject}:\n\n";
         $namefqdn = $instancename . '.' . $instanceproject . '.' . $instanceregion . '.' . 'wmflabs';
         $host->addAssociatedDomain($namefqdn);
     }
 }