ReleaseImages.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. <?php
  2. namespace FD3;
  3. use Docker\Composer\FileFormat;
  4. use Docker\Composer\NetworkConfig;
  5. use Docker\Composer\ServiceNotFoundException;
  6. use FD3\Services\Amqp;
  7. use FD3\Services\Api;
  8. use FD3\Services\Base;
  9. use FD3\Services\Base_log;
  10. use FD3\Services\Cablemodem;
  11. use FD3\Services\Cablemodem_cmd;
  12. use FD3\Services\Cablemodem_task;
  13. use FD3\Services\Dhcp;
  14. use FD3\Services\Dhcp_task;
  15. use FD3\Services\Freeradius;
  16. use FD3\Services\Ftth;
  17. use FD3\Services\Ftth_cmd;
  18. use FD3\Services\Ftth_task;
  19. use FD3\Services\Genieacs_cwmp;
  20. use FD3\Services\Genieacs_fs;
  21. use FD3\Services\Genieacs_gui;
  22. use FD3\Services\Genieacs_nbi;
  23. use FD3\Services\Geoserver;
  24. use FD3\Services\InitialService;
  25. use FD3\Services\Jsendpoint;
  26. use FD3\Services\Jsonep_mongo;
  27. use FD3\Services\Jsonep_mysql;
  28. use FD3\Services\Kea;
  29. use FD3\Services\Mongodb;
  30. use FD3\Services\Mysql;
  31. use FD3\Services\Nginx;
  32. use FD3\Services\Pma;
  33. use FD3\Services\Radius;
  34. use FD3\Services\Radius_task;
  35. use FD3\Services\Redis;
  36. use FD3\Services\Stats;
  37. use FD3\Services\Stats_cmd;
  38. use FD3\Services\Statsd;
  39. use FD3\Services\Supervisord;
  40. use FD3\Services\Swagger;
  41. use FD3\Services\Tftp;
  42. use Symfony\Component\Console\Command\Command;
  43. use Symfony\Component\Console\Exception\LogicException;
  44. use Symfony\Component\Console\Formatter\OutputFormatterStyle;
  45. use Symfony\Component\Console\Input\InputArgument;
  46. use Symfony\Component\Console\Input\InputInterface;
  47. use Symfony\Component\Console\Input\InputOption;
  48. use Symfony\Component\Console\Output\OutputInterface;
  49. use Symfony\Component\Console\Question\ConfirmationQuestion;
  50. use Symfony\Component\Console\Question\Question;
  51. use Symfony\Component\Yaml\Yaml;
  52. class ReleaseImages extends Command
  53. {
  54. /**
  55. * @var string Nombre del archivo de log.
  56. */
  57. protected $_running_log;
  58. /**
  59. * @var string Contiene la politica de restart de los dockers.
  60. */
  61. public $_docker_restart_default;
  62. /**
  63. * @var string Contiene la politica de restart de los dockers de tasks.
  64. */
  65. public $_docker_restart_task;
  66. /**
  67. * @var string Contiene la politica de restart de los dockers.
  68. */
  69. public $_docker_restart_always;
  70. /**
  71. * @var array Contiene las variables que se utilizar en la ejecucion del ansible.
  72. */
  73. protected $_ansible_vars;
  74. /**
  75. * @var string Contiene el password del usuario root.
  76. */
  77. public $_mysql_root_pass;
  78. /**
  79. * @var string Contiene el usuario de base de datos.
  80. */
  81. public $_mysql_user;
  82. /**
  83. * @var string Contiene la contrasena del usuario de base de datos.
  84. */
  85. public $_mysql_pass;
  86. /**
  87. * @var DevOps\FileSystem Me permite crear archivos.
  88. */
  89. protected $_dObj;
  90. /**
  91. * @var string Contiene el dominio.
  92. */
  93. protected $_domain;
  94. /**
  95. * @var string Contiene el nombre del cliente.
  96. */
  97. protected $_client;
  98. /**
  99. * @var array Contiene todos los modulos para la instalacion.
  100. */
  101. public $_modules_all;
  102. /**
  103. * @var array Contiene todos los modulos extras para la instalacion.
  104. */
  105. protected $_modules_extra;
  106. /**
  107. * @var array Contiene la configuracion de los modulos.
  108. */
  109. public $_modules;
  110. /**
  111. * @var array Contiene los usuarios que van a poder acceder al sistema.
  112. */
  113. protected $_user_system;
  114. /**
  115. * @var string $directory Directorio de instalacion
  116. */
  117. protected $directory;
  118. /**
  119. * @var boolean $_use_nginx_links Para indicar si se crean los links nginx entre los modulos
  120. */
  121. protected $_use_nginx_links;
  122. /**
  123. * Add links nginx
  124. */
  125. protected $_add_nginx_links;
  126. /**
  127. * @var int Max connection for mysql
  128. */
  129. public $_mysql_max_connections;
  130. /**
  131. * @var string Link to mysql
  132. */
  133. public $_mysql_link;
  134. /**
  135. * @var string Running env file
  136. */
  137. public $_running_env;
  138. /**
  139. * @var string Host env file
  140. */
  141. public $_host_env;
  142. /**
  143. * @var string IP configuration
  144. */
  145. public $_network_ip;
  146. /**
  147. * @var string Network name
  148. */
  149. public $_network_name;
  150. /**
  151. * @var boolean If FALSE indicates is production and install only images
  152. */
  153. protected $_develop;
  154. /**
  155. * @var string Options for repo and branch
  156. */
  157. protected $_option_repo = [];
  158. /**
  159. * Constructor.
  160. *
  161. * @param string|null $name The name of the command; passing null means it must be set in configure()
  162. *
  163. * @throws LogicException When the command name is empty
  164. */
  165. public function __construct($name = null)
  166. {
  167. parent::__construct($name);
  168. $this->_running_log = "running.log";
  169. $this->_mysql_user = "iksop";
  170. $this->_mysql_pass = "235r2342gtfsw";
  171. $this->_mysql_root_pass = "235r2342gtfsw";
  172. $this->_mysql_max_connections = 10000;
  173. $this->_mysql_link = "mysql:mysql";
  174. $this->_running_env = "running.env";
  175. $this->_host_env = "host.env";
  176. $this->_docker_restart_default = "on-failure:10";
  177. $this->_docker_restart_task = "on-failure";
  178. $this->_docker_restart_always = "always";
  179. $this->_network_name = "flowdat3";
  180. $this->_user_system = ['users' =>
  181. [
  182. ['user' => 'admin', 'password' => 'admin', 'tenancy' => 1, 'email' => 'soporte@interlink.com.ar', 'extra' => '--super-admin '],
  183. ['user' => 'iksop', 'password' => 'gran5pe', 'tenancy' => 2, 'email' => 'admin@interlink.com.ar', 'extra' => ''],
  184. ['user' => 'interno', 'password' => 'gran5pe1nterno', 'tenancy' => 2, 'email' => 'admin@interlink.com.ar', 'extra' => '']
  185. ]];
  186. $this->_modules = array();
  187. $this->_ansible_vars = array();
  188. $this->_modules_all = $this->getModules();
  189. $this->_add_nginx_links = false;
  190. }
  191. protected function getModules()
  192. {
  193. $dir = __DIR__ . "/Services/";
  194. $files = scandir($dir);
  195. $modulesRead = [];
  196. $resp = [];
  197. foreach ($files as $file) {
  198. if (is_file($dir . $file) && $file != "InitialService.php") {
  199. $class = "FD3\\Services\\" . explode(".", $file)[0];
  200. $object = new $class();
  201. array_push($modulesRead, $object);
  202. }
  203. }
  204. // obtengo los modulos requeridos por obligacion
  205. foreach ($modulesRead as $key => $mod) {
  206. if ($mod->isRequired()) {
  207. $resp[$mod->getModuleName()] = $mod->getConfig();
  208. unset($modulesRead[$key]);
  209. }
  210. }
  211. // obtengo los modulos sin dependencias
  212. foreach ($modulesRead as $key => $mod) {
  213. if (count($mod->getDepends()) == 0) {
  214. $resp[$mod->getModuleName()] = $mod->getConfig();
  215. unset($modulesRead[$key]);
  216. }
  217. }
  218. // obtengo el resto de los modulos
  219. foreach ($modulesRead as $mod) {
  220. $resp[$mod->getModuleName()] = $mod->getConfig();
  221. }
  222. return $resp;
  223. }
  224. protected function configure()
  225. {
  226. $this
  227. ->setName('make:installImages')
  228. ->setDescription('Create a new install.')
  229. ->setHelp('This command allows you to create a new installation...')
  230. ->addArgument('dir', InputArgument::REQUIRED, 'The directory where to create the installation.')
  231. ->addOption('host_ip', null, InputOption::VALUE_REQUIRED, 'Ip of the runnning host to be added to the /etc/hosts file, eventually', "127.0.1.1")
  232. ->addOption('domain', null, InputOption::VALUE_REQUIRED, 'Domain where the flowdat will be installed', "flowdat.net")
  233. ->addOption('client', null, InputOption::VALUE_REQUIRED, 'Client name, if is not provided uses, the dirname of the installation', false)
  234. ->addOption('ip_network_begin', null, InputOption::VALUE_OPTIONAL, 'Flowdat ip network configuration', "172.16.0.0")
  235. ->addOption('branch', null, InputOption::VALUE_OPTIONAL, 'Branch to install. Ej. v0.1.1', "latest")
  236. ->addOption('develop', null, InputOption::VALUE_OPTIONAL, 'If true or 1 then install images and source code.', false)
  237. ->addOption('public_ip', null, InputOption::VALUE_OPTIONAL, 'Public IP of server', false)
  238. ->addOption('ini_file', null, InputOption::VALUE_OPTIONAL, 'Ini file with git repositories urls', './modules.ini')
  239. ;
  240. }
  241. protected function colors(OutputInterface $output)
  242. {
  243. $green = new OutputFormatterStyle('green');
  244. $output->getFormatter()->setStyle('green', $green);
  245. $blue = new OutputFormatterStyle('blue');
  246. $output->getFormatter()->setStyle('blue', $blue);
  247. $red = new OutputFormatterStyle('red');
  248. $output->getFormatter()->setStyle('red', $red);
  249. $bold = new OutputFormatterStyle(null, null, ['bold']);
  250. $output->getFormatter()->setStyle('bold', $bold);
  251. }
  252. protected function execute(InputInterface $input, OutputInterface $output)
  253. {
  254. try {
  255. $this->colors($output);
  256. // seteo todos los modulos a instalar por defecto
  257. $modules = $this->selectInstallModules($input, $output);
  258. $this->AddModules(explode(",", $modules));
  259. $this->directory = $input->getArgument('dir');
  260. if (!is_dir($this->directory)) {
  261. mkdir($this->directory, 0777, true);
  262. }
  263. if (file_exists($this->directory . "/" . $this->_running_log)) {
  264. $helper = $this->getHelper('question');
  265. $question = new ConfirmationQuestion('The ' . realpath($this->directory) . "/" . $this->_running_log . ' file exist. Read file (Y) or take parameters (N)? (Y/n)', true);
  266. if ($helper->ask($input, $output, $question)) {
  267. $this->setParametersFormFile($input);
  268. }
  269. }
  270. $this->_domain = $input->getOption("domain");
  271. $this->_client = $input->getOption("client");
  272. $this->_develop = $input->getOption("develop") === "true" || $input->getOption("develop") === "1";
  273. $this->_network_ip = $input->getOption("ip_network_begin");
  274. if (!$this->_client) {
  275. $this->_client = basename(realpath($this->directory));
  276. }
  277. $version = $input->getOption("branch");
  278. $internal_user_id = 2;
  279. $this->_ansible_vars["DOMAIN"] = $this->_domain;
  280. $this->_ansible_vars["CLIENT"] = $this->_client;
  281. $this->_ansible_vars["CMD_USERNAME"] = $this->_user_system['users'][$internal_user_id]['user'];
  282. $this->_ansible_vars["CMD_PASSWORD"] = $this->_user_system['users'][$internal_user_id]['password'];
  283. $this->_ansible_vars["ENV_LIST"] = "prod,dev,test";
  284. $this->_ansible_vars["API_CIDR"] = "172.16.0.0/16";
  285. $this->_ansible_vars["IK_SUBRED"] = "200.50.160.0/21";
  286. $this->_ansible_vars["MYSQL_ROOT_PASSWORD"] = $this->_mysql_root_pass;
  287. $this->_add_nginx_links = true;
  288. $dObj = new DevOps\FileSystem(realpath($this->directory));
  289. $dObj->dirExists()->realpath();
  290. $this->_dObj = $dObj;
  291. // agrego las opciones del input a la configuracion _modues
  292. $this->addConfigOptions($input, $version);
  293. // creo el archivo de log de como se ejecuto
  294. $this->createFileRunning($input, $output);
  295. // cargo las fuentes a clonar
  296. $this->createGitClone($input);
  297. // creo el archivo docker-compose.yml
  298. $this->getDockerComposer($version, "docker.infra.flowdat.com/");
  299. // escribo el archivo de host
  300. $this->writeHostsFile($input->getOption("host_ip"));
  301. // escribo el archivo con las variables de entorno
  302. $this->writeHostEnv();
  303. // escribo los archivo oauth
  304. $this->writeOAUTH();
  305. // escribo un archivo con variables para ansible
  306. $this->writeEnvVariables();
  307. $dObj->file('install.yml')->content(
  308. yaml::dump(array(
  309. "install_dir" => realpath($this->directory),
  310. 'docker_apps' => implode(",", $this->_ansible_vars),
  311. 'domain' => $this->_domain,
  312. )
  313. )
  314. );
  315. $dObj->file('ansible.cfg')->content(
  316. "[defaults]\n" .
  317. "inventory=inventory.ini\n" .
  318. "gather_timeout=30\n"
  319. );
  320. // Copio el archivo hosts por defecto que reemplaza el /etc/hosts en cada container
  321. $path = $dObj->dirExists()->realpath()->getPath();
  322. copy(getcwd() . "/hosts", $path . "/hosts");
  323. $this->public_ip = $input->getOption('public_ip');
  324. while (!filter_var($this->public_ip, FILTER_VALIDATE_IP)) {
  325. $helper = $this->getHelper('question');
  326. $question = new Question('IP pública del cliente para acceder a Flowdat ? (Default: 127.0.0.1)', '127.0.0.1');
  327. $this->public_ip = $helper->ask($input, $output, $question);
  328. }
  329. $this->addHosts();
  330. // copio el playbook
  331. if ($this->_develop) {
  332. copy(getcwd() . "/playbook.yml", $path . "/playbook.yml");
  333. } else {
  334. copy(getcwd() . "/playbookSupport.yml", $path . "/playbook.yml");
  335. copy(getcwd() . "/get_supervisord_files.sh", $path . "/get_supervisord_files.sh");
  336. // KEA selected for install, copy the file get_kea_files.sh
  337. // otherwise delete the file if exists in the path
  338. $keaFile = "{$path}/get_kea_files.sh";
  339. if ($this->isModuleAvailable(new Kea())) {
  340. copy(getcwd() . "/get_kea_files.sh", $keaFile);
  341. } elseif (file_exists($keaFile) === true) {
  342. unlink($keaFile);
  343. }
  344. }
  345. // copio el script de base de datos inicial
  346. copy(getcwd() . "/mysql_scripts.sql", $path . "/mysql_scripts.sql");
  347. // copio script mysql schema freeradius
  348. copy(getcwd() . "/mysql/freeradius/schema.sql", $path . "/freeradius_schema.sql");
  349. // copio el docker-compose.service
  350. copy(getcwd() . "/docker-compose.service", $path . "/docker-compose.service");
  351. } catch (\Throwable $t) {
  352. $output->writeln($t->getTraceAsString());
  353. } finally {
  354. $this->_dObj = null;
  355. $this->_modules = null;
  356. }
  357. }
  358. /**
  359. * @param string $module Name of module.
  360. * @return bool Return TRUE if depends exists.
  361. */
  362. public function needInstallModule($module)
  363. {
  364. foreach ($this->_modules as $key => $value) {
  365. if ($key == $module) {
  366. return true;
  367. }
  368. }
  369. return false;
  370. }
  371. /**
  372. * @param array $modules All modules selected.
  373. * @param array $depends All modules to depends.
  374. * @return bool Return TRUE if depends exists.
  375. */
  376. public function checkDepends($modules, $depends)
  377. {
  378. if ($depends) {
  379. foreach ($depends as $depend) {
  380. if (in_array($depend, $modules)) {
  381. return true;
  382. }
  383. }
  384. }
  385. return false;
  386. }
  387. /**
  388. * @param InputInterface $input InputInterface
  389. * @param OutputInterface $output OutputInterface
  390. * @param bool $update
  391. * @return string Return all modules selected.
  392. */
  393. public function selectInstallModules(InputInterface $input, OutputInterface $output, $update = false)
  394. {
  395. $modules = [];
  396. $output->writeln("Seleccione los módulos que desea instalar:");
  397. foreach ($this->_modules_all as $name => $value) {
  398. if (isset($value['REQUIRED']) && $value['REQUIRED']) {
  399. $modules[] = $name;
  400. $output->writeln("<green>Se instala el modulo $name, por ser una dependencia obligatoria</green>");
  401. } else {
  402. if ($this->checkDepends($modules, $value['DEPENDS'])) {
  403. $modules[] = $name;
  404. $value['REQUIRED'] = true;
  405. $output->writeln("<blue>Se instala el modulo $name, por tener las siguientes dependencias " .
  406. implode(",", $value['DEPENDS']) . "</blue>");
  407. } else {
  408. $helper = $this->getHelper('question');
  409. $defaultQuestionYes = "(<green>Y</green>/n)";
  410. $defaultQuestionNo = "(y/<red>N</red>)";
  411. $def = $defaultQuestionYes;
  412. if (!$value["DEFAULTINSTALATION"]) {
  413. $def = $defaultQuestionNo;
  414. }
  415. if ($value['INSTALLED']) {
  416. $installed = " <red>*** MODULO YA INSTALADO ***</red> ";
  417. if ($update) {
  418. $def = $defaultQuestionYes;
  419. }
  420. } else {
  421. $installed = "";
  422. if ($update) {
  423. $def = $defaultQuestionNo;
  424. }
  425. }
  426. $question = new ConfirmationQuestion($installed . (isset($value['HELP']) ? ($value['HELP'] . ". ") : "") .
  427. strtoupper($name) . "? $def ",
  428. $defaultQuestionYes == $def);
  429. if ($helper->ask($input, $output, $question)) {
  430. $modules [] = $name;
  431. $value['REQUIRED'] = true;
  432. }
  433. }
  434. }
  435. }
  436. $modules = implode(",", $modules);
  437. return $modules;
  438. }
  439. /**
  440. * @return array Retorna un array con los host como key el dominio como valor.
  441. */
  442. function getHostEnv()
  443. {
  444. $resp = array();
  445. // agrego todos los host. Esto se necesita para cuando no se instala completo
  446. foreach ($this->_modules_all as $key => $values) {
  447. if (isset($values['HOST_ENV']) && $values['HOST_ENV']) {
  448. $resp ["HOST_" . strtoupper($key)] = "";
  449. }
  450. }
  451. // agrego las url solo a los que voy a instalar
  452. foreach ($this->_modules as $key => $values) {
  453. if (isset($values['HOST_ENV']) && $values['HOST_ENV']) {
  454. $resp ["HOST_" . strtoupper($key)] = $this->getDomain($key);
  455. }
  456. }
  457. return $resp;
  458. }
  459. function getHostConfig($config_ip)
  460. {
  461. $resp = array();
  462. foreach ($this->_modules as $key => $values) {
  463. if (isset($values['HOST_ENV']) && $values['HOST_ENV']) {
  464. $resp [$this->getDomain($key)] = $config_ip;
  465. }
  466. }
  467. return $resp;
  468. }
  469. function getDockerComposer($version = "latest", $registry = "docker.infra.flowdat.com/")
  470. {
  471. $composer = new FileFormat("../", "3.7");
  472. $this->registerVolumes($composer);
  473. $nc = new NetworkConfig();
  474. $nc->addDriver()->addSubnetGateway("172.16.0.0/16");
  475. $composer->getNetwork()->addDriver($this->_network_name)->addConfig($this->_network_name, $nc);
  476. $base_vars = array(
  477. "version" => $version,
  478. "host_env_file" => $this->_host_env,
  479. "registry" => $registry);
  480. $ip = explode(".", $this->_network_ip);
  481. array_pop($ip);
  482. $ip = implode(".", $ip);
  483. foreach ($this->_modules_all as $module => $env) {
  484. if (strpos($module, "genieacs") !== false) {
  485. $module = str_replace("-", "_", $module);
  486. }
  487. $class = "FD3\\Services\\" . ucfirst($module);
  488. $object = new $class();
  489. $object
  490. ->setRelease($this)
  491. ->setComposer($composer)
  492. ->setConfigVar($base_vars)
  493. ->setIp($ip)
  494. ->setProduction(!$this->_develop)
  495. ->add();
  496. }
  497. $this->_dObj->file("docker-compose.yml")->content($composer->render());
  498. // escribo un archivo inventory.ini por defecto para no tener que lanzar los docker
  499. $this->writeInventory($composer);
  500. }
  501. /**
  502. * Write hosts file with ips of docker containers
  503. */
  504. protected function addHosts()
  505. {
  506. $composer = new FileFormat("../", "3.7");
  507. $ip = explode(".", $this->_network_ip);
  508. array_pop($ip);
  509. $ip = implode(".", $ip);
  510. $ips = [];
  511. foreach ($this->_modules_all as $module => $env) {
  512. if (strpos($module, "genieacs") !== false) {
  513. $module = str_replace("-", "_", $module);
  514. }
  515. $class = "FD3\\Services\\" . ucfirst($module);
  516. $object = new $class();
  517. $object
  518. ->setRelease($this)
  519. ->setComposer($composer)
  520. ->setIp($ip)
  521. ->setProduction(!$this->_develop)
  522. ->add();
  523. if ($this->needInstallModule($module)) {
  524. $ips[$module] = $object->generateIP();
  525. }
  526. }
  527. $path = $this->_dObj->dirExists()->realpath()->getPath();
  528. $contents = file_get_contents($path . "/hosts") . "\n";
  529. if (count($ips)) {
  530. ksort($ips);
  531. }
  532. foreach ($ips as $module => $ip) {
  533. $contents .= "{$ip} {$module}\n";
  534. }
  535. $modules = [
  536. new Base(),
  537. new Ftth(),
  538. new Cablemodem(),
  539. new Stats(),
  540. new Dhcp(),
  541. new Radius(),
  542. ];
  543. foreach ($modules as $module) {
  544. if ($this->isModuleAvailable($module)) {
  545. $domain = $this->getDomain(($module)->getModuleName());
  546. $contents .= "{$this->public_ip} {$domain}\n";
  547. }
  548. }
  549. file_put_contents($path . "/hosts", $contents);
  550. }
  551. /**
  552. * Crea un array con la configuracion de los modulos.
  553. * @param InputInterface $input Contiene el input.
  554. * @param String $version Version to install.
  555. */
  556. protected function addConfigOptions(InputInterface $input, $version)
  557. {
  558. $file = $input->getOption('ini_file');
  559. $repositories = parse_ini_file($file, true);
  560. if (strtolower($version) === 'latest') {
  561. $version = "master";
  562. }
  563. foreach ($this->_modules as $key => $values) {
  564. $modifyKey = false;
  565. $new_key = $key;
  566. if ($new_key == (new Jsendpoint())->getModuleName() ||
  567. $new_key == (new Jsonep_mysql())->getModuleName() ||
  568. $new_key == (new Jsonep_mongo())->getModuleName()) {
  569. // los jsendpoint estan dentro del statsd
  570. $new_key = "statsd";
  571. $modifyKey = true;
  572. } elseif ($new_key == (new Genieacs_cwmp())->getModuleName() ||
  573. $new_key == (new Genieacs_fs())->getModuleName() ||
  574. $new_key == (new Genieacs_nbi())->getModuleName() ||
  575. $new_key == (new Genieacs_gui())->getModuleName()) {
  576. // agrego cualquier genieacs
  577. $new_key = "genieacs";
  578. $modifyKey = true;
  579. }
  580. foreach ($repositories as $keyRepo => $valueRepo) {
  581. if ($new_key == $keyRepo) {
  582. if ($modifyKey) {
  583. $this->_modules[$new_key]['repo'] = $repositories[$keyRepo]["repo"];
  584. $this->_modules[$new_key]['ref'] = $version;
  585. } else {
  586. $this->_modules[$key]['repo'] = $repositories[$keyRepo]["repo"];
  587. $this->_modules[$key]['ref'] = $version;
  588. }
  589. }
  590. }
  591. }
  592. }
  593. /**
  594. * Crea un array con las direcciones de a clonar.
  595. */
  596. protected function createGitClone(InputInterface $input, $version = 'latest')
  597. {
  598. $clone = array();
  599. $modules = array_keys($this->_modules);
  600. foreach ($modules as $name) {
  601. if (isset($this->_modules[$name]["repo"]) &&
  602. isset($this->_modules[$name]["ref"])) {
  603. $clone[$name] = array(
  604. 'url' => $this->_modules[$name]["repo"],
  605. 'branch' => $this->_modules[$name]["ref"]
  606. );
  607. }
  608. }
  609. if ($this->_develop) {
  610. // agrego fuentes que no son modulos
  611. $file = $input->getOption('ini_file');
  612. $repositories = parse_ini_file($file, true);
  613. if (strtolower($version) === 'latest') {
  614. $version = "master";
  615. }
  616. $mod = 'connect';
  617. $clone[$mod] = array(
  618. 'url' => $repositories[$mod]["repo"],
  619. 'branch' => $version
  620. );
  621. $mod = 'netmiko';
  622. $clone[$mod] = array(
  623. 'url' => $repositories[$mod]["repo"],
  624. 'branch' => $version
  625. );
  626. $mod = 'ciscoconf';
  627. $clone[$mod] = array(
  628. 'url' => $repositories[$mod]["repo"],
  629. 'branch' => $version
  630. );
  631. }
  632. $this->_dObj->file("git.ini")->writeIniConfig($clone);
  633. }
  634. /**
  635. * Crea un archivo conlos parametros con los que se corrio el script.
  636. * @param InputInterface $input Contiene el input
  637. * @param OutputInterface $output Contiene el output
  638. */
  639. protected function createFileRunning(InputInterface $input, OutputInterface $output)
  640. {
  641. $file = array();
  642. $file ["Running"] = array("date" => gmdate('Y-m-d h:i:s'));
  643. $file ["Arguments"] = $input->getArguments();
  644. $file ["Options"] = $input->getOptions();
  645. $file ["Options"]["modules"] = implode(",", array_keys($this->_modules));
  646. $output->writeln("Writing " . $this->_dObj->getPath() . "/" . $this->_running_log);
  647. $this->_dObj->file($this->_running_log)->writeIniConfig($file);
  648. }
  649. /**
  650. * @param string $module Contiene el nombre del modulo.
  651. * @param array $extras Contiene variables de entorno extra.
  652. * @return string|array Retorna un array con los datos de virtual host.
  653. */
  654. function getEnviromentVarialbes($module, $extras = array())
  655. {
  656. $env = "";
  657. if ($module != null) {
  658. foreach ($this->_modules as $nameApp => $app) {
  659. if (isset($app['VAR_ENV']) && $nameApp == $module) {
  660. foreach ($app['VAR_ENV'] as $key => $value) {
  661. if ($key == 'VIRTUAL_HOST') {
  662. $env .= "VIRTUAL_HOST=" . $this->getDomain($module) . "\n";
  663. } else {
  664. $env .= $key . "=" . $value . "\n";
  665. }
  666. }
  667. }
  668. }
  669. }
  670. foreach ($extras as $key => $value) {
  671. $env .= $key . "=" . $value . "\n";
  672. }
  673. return $env;
  674. }
  675. /**
  676. * Crea el archivo modulo.oauth.env
  677. */
  678. protected function writeOAUTH()
  679. {
  680. $oautModules = "";
  681. foreach ($this->_modules as $nameApp => $app) {
  682. if (isset($app['OAUTH']) && $app['OAUTH']) {
  683. if (!file_exists(realpath($this->directory) . $nameApp . ".oauth.env")) {
  684. $this->_dObj->file($nameApp . ".oauth.env")->content("");
  685. $oautModules = $oautModules . $nameApp . ",";
  686. }
  687. }
  688. }
  689. $this->_ansible_vars["MODULES_INSTALL"] = "base," . substr($oautModules, 0, strlen($oautModules) - 1);
  690. }
  691. /**
  692. * Crea el archivo host.env
  693. */
  694. protected function writeHostEnv()
  695. {
  696. $hostEnvConfig = $this->getHostEnv();
  697. $env_content = "";
  698. foreach ($hostEnvConfig as $var => $val) {
  699. $env_content .= $var . "=" . $val . "\n";
  700. }
  701. $this->_dObj->file($this->_host_env)->content($env_content);
  702. }
  703. /**
  704. * Crea el archivo hostsDile
  705. * @param string $config_ip Contiene la ip.
  706. */
  707. protected function writeHostsFile($config_ip)
  708. {
  709. $hostConfig = $this->getHostConfig($config_ip);
  710. $hostfile_content = "";
  711. foreach ($hostConfig as $host => $ip) {
  712. $hostfile_content .= $ip . "\t" . $host . "\n";
  713. }
  714. $this->_dObj->file("hostsFile")->content($hostfile_content);
  715. }
  716. /**
  717. * Crea un archivo con las variables de entorno particulares del modulo.
  718. * @param string $name Contiene el nombre del archivo.
  719. * @param string $module Contiene el nombre del modulo.
  720. * @param array $extras Contiene un array con las variables extras.
  721. */
  722. public function writeVariablesEnviroment($name, $module = null, $extras = array())
  723. {
  724. $this->_dObj->file($name)->content(
  725. $this->getEnviromentVarialbes($module, $extras));
  726. }
  727. /**
  728. * Funcion que agrega el build de acuerdo en la configuracion.
  729. * @param string $module Contiene el nombre del modulo.
  730. * @param FileFormat $composer Contiene el objeto FileFormat.
  731. */
  732. public function addBuild($module, FileFormat $composer)
  733. {
  734. if (isset($this->_modules[$module]['build']) &&
  735. filter_var($this->_modules[$module]['build'], FILTER_VALIDATE_BOOLEAN)) {
  736. try {
  737. $composer->service($module)->build("./$module/");
  738. } catch (ServiceNotFoundException $ignore) {
  739. }
  740. }
  741. }
  742. /**
  743. * Funcion que setea los valores que se lean desde el archivo running.log.
  744. * Solo se reemplazan las opciones.
  745. * Si se toman los argumentos puede pisar el directorio de destino y a lo mejor se quiere replicar la instalacion en
  746. * otro directorio.
  747. * @param InputInterface $input contiene el input
  748. */
  749. protected function setParametersFormFile(InputInterface $input)
  750. {
  751. $parameters = parse_ini_file($input->getArgument('dir') . "/" . $this->_running_log, true);
  752. foreach ($parameters["Options"] as $key => $value) {
  753. $this->_option_repo[$key] = $value;
  754. }
  755. }
  756. /**
  757. * @param string $module Contiene el nombre del modulo.
  758. * @return string Retorna el dominio para el modulo.
  759. */
  760. public function getDomain($module)
  761. {
  762. return $module . "." . $this->_client . "." . $this->_domain;
  763. }
  764. /**
  765. * @param array $modules Contiene los modulos a implementar
  766. */
  767. protected function AddModules($modules)
  768. {
  769. foreach ($modules as $value) {
  770. if (array_key_exists($value, $this->_modules_all)) {
  771. $this->_modules[$value] = $this->_modules_all[$value];
  772. }
  773. }
  774. }
  775. /**
  776. * Crea el archivo con las variables para ejecutar el ansible.
  777. */
  778. protected function writeEnvVariables()
  779. {
  780. $tmp = "";
  781. foreach ($this->_ansible_vars as $key => $value) {
  782. $tmp = $tmp . "$key=$value\n";
  783. }
  784. $this->_dObj->file(str_replace(".log", ".env", $this->_running_log))
  785. ->content($tmp);
  786. }
  787. /**
  788. * Crea el archivo con las variables para ejecutar el ansible.
  789. */
  790. protected function writeInventory(FileFormat $composer)
  791. {
  792. $tmp = "";
  793. $all = "[all]\n";
  794. $prefix = basename(realpath($this->directory));
  795. foreach ($composer->getServices() as $key => $value) {
  796. $tmp .= "[$key]\n";
  797. $tmp .= $prefix . "_" . $key . "_1\n\n";
  798. $all .= $prefix . "_" . $key . "_1\n";
  799. }
  800. $this->_dObj->file("inventory.ini")->content($tmp . $all);
  801. }
  802. /**
  803. * Funcion que agrega links nginx a los modulos principales (para instalacion dev)
  804. * @param string $module Contiene el nombre del modulo.
  805. * @param FileFormat $composer Contiene el objeto FileFormat.
  806. * @throws ServiceNotFoundException
  807. */
  808. public function addNginxLinks($module, FileFormat $composer)
  809. {
  810. if ($this->_add_nginx_links) {
  811. if ($this->isModuleAvailable(new Base())) {
  812. $composer->service($module)->addLinks((new Nginx())->getModuleName(), $this->getDomain((new Base())->getModuleName()));
  813. }
  814. if ($this->isModuleAvailable(new Ftth())) {
  815. $composer->service($module)->addLinks((new Nginx())->getModuleName(), $this->getDomain((new Ftth())->getModuleName()));
  816. }
  817. if ($this->isModuleAvailable(new Cablemodem())) {
  818. $composer->service($module)->addLinks((new Nginx())->getModuleName(), $this->getDomain((new Cablemodem())->getModuleName()));
  819. }
  820. if ($this->isModuleAvailable(new Stats())) {
  821. $composer->service($module)->addLinks((new Nginx())->getModuleName(), $this->getDomain((new Stats())->getModuleName()));
  822. }
  823. if ($this->isModuleAvailable(new Dhcp())) {
  824. $composer->service($module)->addLinks((new Nginx())->getModuleName(), $this->getDomain((new Dhcp())->getModuleName()));
  825. }
  826. if ($this->isModuleAvailable(new Radius())) {
  827. $composer->service($module)->addLinks((new Nginx())->getModuleName(), $this->getDomain((new Radius())->getModuleName()));
  828. }
  829. }
  830. }
  831. /**
  832. * Register volumes only for installed modules
  833. * @param FileFormat $composer
  834. */
  835. protected function registerVolumes(FileFormat $composer)
  836. {
  837. if ($this->isModuleAvailable(new Pma())) {
  838. $composer->getVolumes()->addVolumen(Pma::PMA_VOLUMEN, 'local');
  839. }
  840. if ($this->isModuleAvailable(new Swagger())) {
  841. $composer->getVolumes()->addVolumen(Swagger::SWAGGER_VOLUMEN, 'local');
  842. }
  843. if ($this->isModuleAvailable(new Base())) {
  844. $composer->getVolumes()
  845. ->addVolumen(Base::BASE_SOCKET_VOLUMEN, 'local')
  846. ->addVolumen(Nginx::BASE_NGINX_VOLUMEN, 'local');
  847. }
  848. if ($this->isModuleAvailable(new Cablemodem())) {
  849. $composer->getVolumes()
  850. ->addVolumen(Cablemodem::CABLEMODEM_SOCKET_VOLUMEN, 'local')
  851. ->addVolumen(Nginx::CABLEMODEM_NGINX_VOLUMEN, 'local');
  852. }
  853. if ($this->isModuleAvailable(new Dhcp())) {
  854. $composer->getVolumes()
  855. ->addVolumen(Dhcp::DHCP_SOCKET_VOLUMEN, 'local')
  856. ->addVolumen(Dhcp::DHCP_KEA_VOLUMEN, 'local')
  857. ->addVolumen(Nginx::DHCP_NGINX_VOLUMEN, 'local');
  858. }
  859. if ($this->isModuleAvailable(new Ftth())) {
  860. $composer->getVolumes()
  861. ->addVolumen(Ftth::FTTH_SOCKET_VOLUMEN, 'local')
  862. ->addVolumen(Ftth::FTTH_SUPERVISORD_VOLUMEN, 'local')
  863. ->addVolumen(Nginx::FTTH_NGINX_VOLUMEN, 'local');
  864. }
  865. if ($this->isModuleAvailable(new Radius())) {
  866. $composer->getVolumes()
  867. ->addVolumen(Radius::RADIUS_SOCKET_VOLUMEN, 'local')
  868. ->addVolumen(Nginx::RADIUS_NGINX_VOLUMEN, 'local');
  869. }
  870. if ($this->isModuleAvailable(new Stats())) {
  871. $composer->getVolumes()
  872. ->addVolumen(Stats::STATS_SOCKET_VOLUMEN, 'local')
  873. ->addVolumen(Stats::STATS_SUPERVISORD_VOLUMEN, 'local')
  874. ->addVolumen(Nginx::STATS_NGINX_VOLUMEN, 'local');
  875. }
  876. if ($this->isModuleAvailable(new Api())) {
  877. $composer->getVolumes()
  878. ->addVolumen(Api::API_SOCKET_VOLUMEN, 'local')
  879. ->addVolumen(Nginx::API_NGINX_VOLUMEN, 'local');
  880. }
  881. }
  882. public function isModuleAvailable(InitialService $object)
  883. {
  884. return array_key_exists($object->getModuleName(), $this->_modules);
  885. }
  886. }