Explorar o código

Merged master into FD3-682

Luciano Andrade %!s(int64=6) %!d(string=hai) anos
pai
achega
1bf6bd1e4e

+ 6 - 1
src/HostBundle/Admin/HostAdmin.php

@@ -52,7 +52,7 @@ class HostAdmin extends BaseAdmin
             ->add('hostType')
             ->add('state')
             ->add('options.fixed_address')
-            ->add('host')
+            ->add('associatedHosts')
             ->add('_action', null, array(
                 'actions' => array(
                     'show' => array(),
@@ -108,16 +108,21 @@ class HostAdmin extends BaseAdmin
      */
     protected function configureShowFields(ShowMapper $showMapper)
     {
+        $subject = $this->getSubject();
         $showMapper
             ->tab('Host')
             ->with('Host')
             ->add('mac')
             ->add('hostType')
             ->add('state')
+            ->add('associatedHosts')
             ->add('host')
         ->end()
         ->end()
         ;
+        $subject->getAssociatedHosts()->count() ?: $showMapper->remove('associatedHosts');
+        $subject->getHost() ?: $showMapper->remove('host');
+        
 
         $this->addCablemodemTab($showMapper);
     }

+ 51 - 0
src/HostBundle/Command/DHCPOptionsUpdateCommand.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace HostBundle\Command;
+
+use Buzz\Message\RequestInterface as HttpRequestInterface;
+use HostBundle\Entity\Host;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class DHCPOptionsUpdateCommand extends ContainerAwareCommand
+{
+
+    /**
+     * @see Command
+     */
+    protected function configure()
+    {
+        $this
+            ->setName('dhcp:options:update')
+            ->setDescription('Update dhcp options from host')
+            ->setHelp(<<<EOT
+The <info>dhcp:options:update</info> command updates a DHCP options from host
+EOT
+        );
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $io = new SymfonyStyle($input, $output);
+        $dhcpService = $this->getContainer()->get('dhcp.dhcp_options.service');
+        
+        $io->section("Updating Host entities:");
+        
+        $result = $dhcpService->formatDhcpOptions($output);
+        
+        $io->newLine(2);
+        $io->success('Total entities updated: ' . $result);
+        $io->newLine(2);
+        
+        $output->writeln(['', 'Done!']);
+    }
+        
+}

+ 23 - 3
src/HostBundle/Entity/Host.php

@@ -89,20 +89,32 @@ class Host implements WorkflowInterface
     protected $fixedIP = false;
     
     /**
-     * @ORM\ManyToOne(targetEntity="Host", fetch="EXTRA_LAZY")
+     * @ORM\ManyToOne(targetEntity="Host", inversedBy="associatedHosts", fetch="EXTRA_LAZY")
      * @ORM\JoinColumn(name="host_id", referencedColumnName="id", onDelete="SET NULL")
      *
      * @JMS\MaxDepth(1)
      */
     protected $host;
+    
+    /**
+     * @ORM\OneToMany(targetEntity="Host", mappedBy="host", fetch="EXTRA_LAZY")
+     *
+     * @JMS\MaxDepth(1)
+     */
+    protected $associatedHosts;
 
 
+    public function __construct() 
+    {
+        $this->associatedHosts = new \Doctrine\Common\Collections\ArrayCollection();
+    }
+
     /**
      * @return string
      */
     public function __toString()
     {
-        return strval($this->mac);
+        return $this->mac ? strval($this->mac) : sprintf('%s - %s', $this->id, $this->hostType->__toString());
     }
 
     /**
@@ -130,7 +142,7 @@ class Host implements WorkflowInterface
      */
     public function getMac()
     {
-        return $this->mac;
+        return $this->mac ?: ($this->host ? $this->host->getMac() : '');
     }
 
     /**
@@ -233,6 +245,14 @@ class Host implements WorkflowInterface
         return $this;
     }
     
+    /**
+     * @return array<Host>
+     */
+    public function getAssociatedHosts()
+    {
+        return $this->associatedHosts;
+    }
+    
     /**
      * @param ExecutionContextInterface $context
      */

+ 13 - 1
src/HostBundle/EventListener/KEAHostReservationSubscriber.php

@@ -68,13 +68,25 @@ class KEAHostReservationSubscriber implements EventSubscriber
     {
         $entity = $args->getEntity();
         if ($entity instanceof Host) {
+            $query = "SELECT COUNT(*) AS `exists`
+                    FROM information_schema.tables 
+                    WHERE table_schema = 'kea' 
+                    AND table_name = 'hosts';";
+            
+            $databaseConnection = $this->serviceContainer->get('database_connection');
+            $stmt = $databaseConnection->prepare($query);
+            $stmt->execute();
+            $tableExists = $stmt->fetchAll();
+            if (!isset($tableExists[0]['exists']) || $tableExists[0]['exists'] == '0') {
+                return;
+            }
             
             if ($entity->getFixedAddress() && $remove == false) {
                 $query = "
                 INSERT INTO kea.hosts (dhcp_identifier,
                 dhcp_identifier_type,
                 ipv4_address)
-                VALUES :mac,
+                VALUES (:mac,
                 (SELECT type FROM kea.host_identifier_type WHERE name=:type),
                 INET_ATON(:ip));
                 ";

+ 4 - 0
src/HostBundle/Resources/config/services.yml

@@ -42,3 +42,7 @@ services:
         tags:
             - { name: doctrine.event_subscriber, connection: default }    
         
+    dhcp.dhcp_options.service:
+        class: HostBundle\Services\DHCPOptionsService
+        arguments: [ "@doctrine.orm.entity_manager", "@validator" ]
+        

+ 2 - 0
src/HostBundle/Resources/translations/HostBundle.es.yml

@@ -65,6 +65,7 @@ list:
     label_extra_data: Extra Data
     label_status: Estado
     label_host: Host
+    label_associated_hosts: Hosts asociados ( ID - Tipo de host )
     label_options_fixed_address: IP
     
 show:
@@ -105,6 +106,7 @@ show:
     label_status: Estado
     label_fixed_address: Fixed Address
     label_host: Host
+    label_associated_hosts: Hosts asociados ( ID - Tipo de host )
 
 filter:
     label_mac: Mac

+ 217 - 0
src/HostBundle/Services/DHCPOptionsService.php

@@ -0,0 +1,217 @@
+<?php
+
+namespace HostBundle\Services;
+
+use HostBundle\Entity\Host;
+use HostBundle\Entity\HostType;
+use Doctrine\ORM\EntityManager;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+class DHCPOptionsService
+{
+    
+    /**
+     * @var EntityManager
+     */
+    private $em;
+    
+    /**
+     * @var ValidatorInterface
+     */
+    private $validator;
+    
+    
+    /**
+     * @param EntityManager $em
+     * @param ValidatorInterface $validator
+     */
+    public function __construct(EntityManager $em, ValidatorInterface $validator)
+    {
+        $this->em = $em;
+        $this->validator = $validator;
+    }
+    
+    /**
+     * @param OutputInterface $output
+     *
+     * @return int
+     */
+    public function formatDhcpOptions($output)
+    {
+        $i = 0;
+        $batchSize = 20;
+        $detach = [];
+        
+        $hostRepository = $this->em->getRepository(Host::class);
+        $hosts = $hostRepository->findAll();
+        
+        ProgressBar::setFormatDefinition('custom', ' %current%/%max% [%bar%] %percent:3s%% %message%');
+        $progressBar = new ProgressBar($output, count($hosts));
+        $progressBar->setFormat('custom');
+        $progressBar->start();
+        foreach ($hosts as $host) {
+            $mtaOptions = $cpeOptions = '';
+            $options = $host->getOptions();
+            $json_options = json_decode($options, true, 512, JSON_BIGINT_AS_STRING);
+            // las options del host ya tienen formato json
+            if (json_last_error() == JSON_ERROR_NONE) {
+                continue;
+            }
+            
+            $config = $this->setAltDhcpParsing($options, $mtaOptions, $cpeOptions);
+            
+            $progressBar->setMessage('Updating DHCP options...');
+            $host->setDHCPOption($config);
+            $host->setOptions(json_encode($config));
+            
+            $detach[] = $host;
+            $i++;
+            
+            if ($mtaOptions != '') {
+                $progressBar->setMessage('Creating MTA Host...');
+                $mtaHost = $this->createHost('mta', $mtaOptions, $host);
+                if ($mtaHost) {
+                    $detach[] = $mtaHost;
+                    $i++;
+                }
+            }
+            if ($cpeOptions != '') {
+                $progressBar->setMessage('Creating CPE Host...');
+                $cpeHost = $this->createHost('cpe', $cpeOptions, $host);
+                if ($cpeHost) {
+                    $detach[] = $cpeHost;
+                    $i++;
+                }
+            }
+            
+            if (($i % $batchSize) === 0) {
+                $this->em->flush();
+                foreach ($detach as $entity) {
+                    $this->em->detach($entity);
+                }
+                $detach = [];
+            }
+            $progressBar->advance();
+        }
+        $progressBar->finish();
+        
+        $this->em->flush();
+        $this->em->clear();
+        
+        return $i;
+    }
+    
+    /**
+     * Parsea la $config y retorna un array asociativo
+     * @param string $config
+     *
+     * @return array
+     */
+    function setAltDhcpParsing($config, &$mtaOptions = '', &$cpeOptions = '')
+    {
+	    $rtr = json_decode($config, true, 512, JSON_BIGINT_AS_STRING);
+	    if (!is_array($rtr)) {
+		    $rtr = array();
+		    foreach (preg_split("|\n|", $config) as $line) {
+    			$p = preg_split("|\s+|", trim($line));
+    			if (trim($line) === "") continue;
+    			if ($p[0] === "option") {
+    				if ($p[1] === "routers") {
+    					$rtr["routers"] = preg_replace("|;$|", "", $p[2]);
+    				} else if ($p[1] === "subnet-mask") {
+    					$rtr["subnet_mask"] = preg_replace("|;$|", "", $p[2]);
+    				} else if ($p[1] === "broadcast-address") {
+    					$rtr["broadcast_address"] = preg_replace("|;$|", "", $p[2]);
+    				} else if ($p[1] === "domain-name") {
+    					$rtr["domain_name"] = preg_replace("/\"|;$/", "", $p[2]);
+    				} else if ($p[1] === "domain-name-servers") {
+    					$val = implode("", array_slice($p,2));
+    					$rtr["domain_name_servers"] = preg_replace("/;$/", "", $val);
+    				} else if ($p[1] === "log-servers") {
+    					$val = implode("", array_slice($p,2));
+    					$rtr["log_servers"] = preg_replace("/;$/", "", $val);
+    				} else if ($p[1] === "time-servers") {
+    					$val = implode("", array_slice($p,2));
+    					$rtr["time_servers"] = preg_replace("/;$/", "", $val);
+    				} else if ($p[1] === "tftp-server-name") {
+    					$rtr["tftp_server"] = preg_replace("/\"|;$/", "", $p[2]);
+    				} else if ($p[1] === "option122.provisioning-type") {
+    					$rtr["option122.provisioning-type"] = preg_replace("/\"|;$/", "", $p[2]);
+    				} else if ($p[1] === "option122.provisioning-server") {
+    					$rtr["option122.provisioning-server"] = preg_replace("/\"|;$/", "", $p[2]);
+    				} else if ($p[1] === "option122.dhcp-server") {
+    					$rtr["option122.dhcp-server"] = preg_replace("/;$/", "", $p[2]);
+    				} else if ($p[1] === "time-offset") {
+    					$rtr["time_offset"] = preg_replace("/;$/", "", $p[2]);
+                    } else if ($p[1] === "host-name") {
+                        $rtr["host_name"] = preg_replace("/\"|;$/", "", $p[2]);
+    				} else {
+    					throw new \Exception("Option not soported by setAltDhcpParsing ".$line);
+    				}
+    			} else if ($p[0] === "max-lease-time") {
+    					$rtr["max_lease_time"] = preg_replace("/;$/", "", $p[1]);
+    			} else if ($p[0] === "filename") {
+    					$rtr["filename"] = preg_replace("/\"|;$/", "", $p[1]);
+    			} else if ($p[0] === "fixed-address") {
+    					$rtr["fixed_address"] = preg_replace("/;$/", "", $p[1]);
+    			} else if ($p[0] === "next-server") {
+    					$rtr["next_server"] = preg_replace("/;$/", "", $p[1]);
+    			} else if ($p[0] === "default-lease-time") {
+    					$rtr["default_lease_time"] = preg_replace("/;$/", "", $p[1]);
+    			}  else if (strpos($p[0], 'mta.') !== false) {
+                    $mtaOptions .= preg_replace('/mta./', '', $line, 1) . "\n";
+                } else if (strpos($p[0], 'cpe.') !== false) {
+                    $cpeOptions .= preg_replace('/cpe./', '', $line, 1) . "\n";
+                } else {
+    				throw new \Exception("Config not soported by setAltDhcpParsing ".$line);
+    			}
+            }
+        } else {
+            $rtr = (array)$rtr;
+        }
+        
+        return $rtr;
+    }
+    
+    /**
+     * @param string $type
+     * @param string $options
+     * @param Host $entity
+     *
+     * @return Host
+     */
+    public function createHost($type, $options, $entity)
+    {
+        // Creo los hosts mta y cpe asociados
+        $hostTypeRepository = $this->em->getRepository(HostType::class);
+        $hostType = $hostTypeRepository->findOneByShortname($type);
+        $hostRepository = $this->em->getRepository(Host::class);
+        $host = $hostRepository->findOneBy([
+            'host' => $entity,
+            'hostType' => $hostType,
+        ]);
+        if (is_null($host)) {
+            $options = $this->setAltDhcpParsing($options);
+            
+            $host = new Host();
+            $host->setHost($entity);
+            $host->setHostType($hostType);
+            $host->setDHCPOption($options);
+            $host->setOptions(json_encode($options));
+            if (isset($options['fixed_address'])) {
+                $host->setFixedIP(true);
+            }
+        
+            if ($this->validator->validate($host)->count() == 0) {
+                $this->em->persist($host);
+                
+                return $host;
+            }
+        }
+        
+        return null;
+    }
+    
+
+}

+ 4 - 4
src/HostBundle/Traits/DHCPOptionTrait.php

@@ -18,13 +18,13 @@ trait DHCPOptionTrait
     {
         $this->setOptions(json_encode($this->getDHCPOption()));
     }
-
+    
     /**
-     * @ORM\PostLoad
+     *  @ORM\PostLoad
      */
-    public function doDHCPOptionOnPostLoad()
+    public function PostLoad()
     {
-       $this->setDHCPOption((array)json_decode($this->getOptions()));
+        $this->setDHCPOption(json_decode($this->getOptions(), true));
     }
 
     function getDHCPOption()

+ 1 - 0
src/IPv4Bundle/Entity/SubNet.php

@@ -286,4 +286,5 @@ class SubNet implements TenancyIdTraitInterface, WorkflowInterface
             $context->addViolation('subnet.address.error');
         }
     }
+
 }