cambiada nomenclatura de las páginas y añadidos posts de documentacion-robeasir.surge.sh
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 416 KiB After Width: | Height: | Size: 416 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 3.5 MiB After Width: | Height: | Size: 3.5 MiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 168 KiB |
@ -0,0 +1,303 @@
|
|||||||
|
---
|
||||||
|
title: "Práctica 2: Interconexión de Servidores de Bases de Datos"
|
||||||
|
date: 2022-11-27T14:23:15+01:00
|
||||||
|
draft: false
|
||||||
|
image: featured.png
|
||||||
|
categories:
|
||||||
|
- práctica
|
||||||
|
- Administración de Bases de Datos
|
||||||
|
tags:
|
||||||
|
- Oracle
|
||||||
|
- Práctica 2 ABD
|
||||||
|
---
|
||||||
|
|
||||||
|
Las interconexiones de servidores de bases de datos son operaciones que pueden ser muy útiles en
|
||||||
|
diferentes contextos. Básicamente, se trata de acceder a datos que no están almacenados en nuestra base
|
||||||
|
de datos, pudiendo combinarlos con los que ya tenemos.
|
||||||
|
En esta práctica veremos varias formas de crear un enlace entre distintos servidores de bases de datos.
|
||||||
|
Se pide:
|
||||||
|
|
||||||
|
* Realizar un enlace entre dos servidores de bases de datos ORACLE, explicando la configuración
|
||||||
|
necesaria en ambos extremos y demostrando su funcionamiento.
|
||||||
|
* Realizar un enlace entre dos servidores de bases de datos Postgres, explicando la configuración
|
||||||
|
necesaria en ambos extremos y demostrando su funcionamiento.
|
||||||
|
* Realizar un enlace entre un servidor ORACLE y otro Postgres o MySQL empleando Heterogeneus
|
||||||
|
Services
|
||||||
|
|
||||||
|
## Enlace entre dos servidores ORACLE
|
||||||
|
|
||||||
|
En mi caso, las dos máquinas tienen la configuración siguiente; Tienen instalado Rocky 8 Oracle Database 19c Enterprise Edition, y tienen los siguientes nombres e IPs:
|
||||||
|
|
||||||
|
* oracle-maquina1: 192.168.122.204
|
||||||
|
* oracle-maquina2: 192.168.122.80
|
||||||
|
|
||||||
|
En ambas bases de datos existe el usuario roberto y están configuradas para el acceso remoto. Para comprobar que pueden acceder se utiliza el comando tnsping:
|
||||||
|
|
||||||
|
![1](https://i.imgur.com/gbnsKsB.png)
|
||||||
|
|
||||||
|
Ahora, para que los servidores puedan conectarse entre ellos, tenemos que añadir los datos de las máquinas al fichero `/opt/oracle/product/19c/dbhome_1/network/admin/tnsnames.ora`, dejándolos de la siguiente manera:
|
||||||
|
|
||||||
|
* En el fichero dentro de la máquina 1:
|
||||||
|
|
||||||
|
```ora
|
||||||
|
MAQUINA2 =
|
||||||
|
(DESCRIPTION =
|
||||||
|
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.122.80)(PORT = 1521))
|
||||||
|
(CONNECT_DATA =
|
||||||
|
(SERVER = DEDICATED)
|
||||||
|
(SERVICE_NAME = ORCLCDB)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
* En el fichero dentro de la máquina 2:
|
||||||
|
|
||||||
|
```ora
|
||||||
|
MAQUINA1 =
|
||||||
|
(DESCRIPTION =
|
||||||
|
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.122.80)(PORT = 1521))
|
||||||
|
(CONNECT_DATA =
|
||||||
|
(SERVER = DEDICATED)
|
||||||
|
(SERVICE_NAME = ORCLCDB)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Tras eso hay que crear los enlaces haciendo referencia al usuario (roberto). los comandos se ejecutan dentro de oracle:
|
||||||
|
|
||||||
|
* En la máquina 1:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
create database link enlace2 connect to roberto identified by roberto using 'maquina2';
|
||||||
|
```
|
||||||
|
|
||||||
|
* En la máquina 2:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
create database link enlace1 connect to roberto identified by roberto using 'maquina1';
|
||||||
|
```
|
||||||
|
|
||||||
|
Podemos comprobar que se puede acceder remotamente a las tablas:
|
||||||
|
|
||||||
|
![2](https://i.imgur.com/iYYIaiL.png)
|
||||||
|
![3](https://i.imgur.com/2Cu5V0W.png)
|
||||||
|
|
||||||
|
## Enlace entre dos servidores Postgres
|
||||||
|
|
||||||
|
En mi caso, las dos máquinas tienen la configuración siguiente; Tienen instalado Debian 11,MariaDB y PostgreSQL, y tienen los siguientes nombres e IPs:
|
||||||
|
|
||||||
|
* mariadb-maquina1: 192.168.122.97
|
||||||
|
* mariadb-maquina2: 192.168.122.90
|
||||||
|
|
||||||
|
En ambas bases de datos existe el usuario roberto y están configuradas para el acceso remoto.
|
||||||
|
|
||||||
|
Ahora vamos a crear el enlace:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install postgresql-contrib
|
||||||
|
psql -d scott
|
||||||
|
create extension dblink;
|
||||||
|
```
|
||||||
|
|
||||||
|
Una vez hecho eso, tenemos que ejecutar los siguientes comandos:
|
||||||
|
|
||||||
|
* Máquina 1:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT dblink_connect('dblink2','dbname=scott host=192.168.122.90 user=roberto password=roberto');
|
||||||
|
```
|
||||||
|
|
||||||
|
* Máquina 2:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT dblink_connect('dblink1','dbname=scott host=192.168.122.97 user=roberto password=roberto');
|
||||||
|
```
|
||||||
|
|
||||||
|
Tras eso, podemos realizar consultas entre máquinas:
|
||||||
|
|
||||||
|
![4](https://i.imgur.com/qzn6uGb.png)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Enlace entre un servidor ORACLE y uno Postgres
|
||||||
|
|
||||||
|
En este caso las máquinas que voy a conectar son oracle-maquina1 y mariadb-maquina2, por lo que las direcciones IP son las siguientes:
|
||||||
|
|
||||||
|
* oracle-maquina1: 192.168.122.204
|
||||||
|
* mariadb-maquina2: 192.168.122.90
|
||||||
|
|
||||||
|
### Conexión desde Postgres a ORACLE
|
||||||
|
|
||||||
|
Primero descargamos los siguientes paquetes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install libaio1 postgresql-server-dev-all build-essential git alien -y
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora tenemos que descargar el instantclient de oracle, se hace con los siguientes comandos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://download.oracle.com/otn_software/linux/instantclient/218000/oracle-instantclient-basic-21.8.0.0.0-1.el8.x86_64.rpm
|
||||||
|
wget https://download.oracle.com/otn_software/linux/instantclient/218000/oracle-instantclient-devel-21.8.0.0.0-1.el8.x86_64.rpm
|
||||||
|
wget https://download.oracle.com/otn_software/linux/instantclient/218000/oracle-instantclient-sqlplus-21.8.0.0.0-1.el8.x86_64.rpm
|
||||||
|
|
||||||
|
sudo alien -i --scripts oracle-instantclient-*
|
||||||
|
```
|
||||||
|
|
||||||
|
Una vez instalado, con el siguiente comando podemos conectarnos a la base de datos de oracle-maquina1:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sqlplus roberto/roberto@192.168.122.204:1521/ORCLCDB
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora tenemos que descargar y compilar `oracle_fdw`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://github.com/laurenz/oracle_fdw/archive/refs/tags/ORACLE_FDW_2_5_0.zip
|
||||||
|
unzip ORACLE_FDW_2_5_0.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
Renombramos la carpeta:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mv oracle_fdw-ORACLE_FDW_2_5_0/ oracle_fdw
|
||||||
|
```
|
||||||
|
|
||||||
|
Finalmente compilamos el programa:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd oracle_fdw
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora, dentro de psql (y de la base de datos scott) creamos el enlace. Podemos comprobar que se ha creado con \dx:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE EXTENSION oracle_fdw;
|
||||||
|
```
|
||||||
|
|
||||||
|
Creamos el schema en el que se van a importar las bases de datos de Oracle:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
create schema oracle;
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuramos un servidor foráneo que haga referencia a la base de datos Oracle en la otra máquina:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
create server oracle foreign data wrapper oracle_fdw options (dbserver '//192.168.122.204/ORCLCDB');
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora creamos una equivalencia entre un usuario local y el del servidor (aunque en este caso se llaman igual):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
create user mapping for roberto server oracle options (user 'roberto', password 'roberto');
|
||||||
|
```
|
||||||
|
|
||||||
|
Le damos permisos al usuario local sobre el schema de oracle:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grant all privileges on schema oracle to roberto;
|
||||||
|
grant all privileges on foreign server oracle to roberto;
|
||||||
|
```
|
||||||
|
|
||||||
|
Iniciamos sesión en psql con el usuario que hemos indicado en los pasos anteriores, e importamos el esquema remoto:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
psql -U roberto -W -d scott
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
import foreign schema "ROBERTO" from server oracle into oracle;
|
||||||
|
```
|
||||||
|
|
||||||
|
![5](https://i.imgur.com/EypaWU0.png)
|
||||||
|
|
||||||
|
### Conexión desde Oracle a Postgres
|
||||||
|
|
||||||
|
Para realizar la conexión vamos a utilizar ODBC (Open Database Conectivity); y en este caso ya que vamos a realizar la conexión con PostgreSQL, también tenemos que descargar el paquete específico:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dnf install unixODBC postgresql-odbc
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora en el fichero de configuración `/etc/odbcinst.ini` comentamos todas las líneas menos las referentes a postgresql, quedando el fichero de la siguiente manera:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[PostgreSQL]
|
||||||
|
Description = ODBC for PostgreSQL
|
||||||
|
Driver = /usr/lib/psqlodbcw.so
|
||||||
|
Setup = /usr/lib/libodbcpsqlS.so
|
||||||
|
Driver64 = /usr/lib64/psqlodbcw.so
|
||||||
|
Setup64 = /usr/lib64/libodbcpsqlS.so
|
||||||
|
FileUsage = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Para configurar el acceso a la máquina con postgres tenemos que crear en el fichero `/etc/odbc.ini` la siguiente entrada:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[PSQLU]
|
||||||
|
|
||||||
|
Debug = 0
|
||||||
|
CommLog = 0
|
||||||
|
ReadOnly = 0
|
||||||
|
Driver = PostgreSQL
|
||||||
|
Servername = 192.168.122.90
|
||||||
|
Username = roberto
|
||||||
|
Password = roberto
|
||||||
|
Port = 5432
|
||||||
|
Database = scott
|
||||||
|
Trace = 0
|
||||||
|
TraceFile = /tmp/sql.log
|
||||||
|
```
|
||||||
|
|
||||||
|
Podemos comprobar que funciona con isql PSQLU.
|
||||||
|
|
||||||
|
Ahora hay que crear la configuración para que Oracle pueda hacer uso del driver. Para ello tenemos que crear el fichero `/opt/oracle/product/19c/dbhome_1/hs/admin/initPSQLU.ora` con el siguiente contenido:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
HS_FDS_CONNECT_INFO = PSQLU
|
||||||
|
HS_FDS_TRACE_LEVEL = DEBUG
|
||||||
|
HS_FDS_SHAREABLE_NAME = /usr/lib64/psqlodbcw.so
|
||||||
|
HS_LANGUAGE = AMERICAN_AMERICA.WE8ISO8859P1
|
||||||
|
set ODBCINI=/etc/odbc.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
También hay que configurar el listener `/opt/oracle/product/19c/dbhome_1/network/admin/listener.ora`, añadiendo lo siguiente al final:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SID_LIST_LISTENER =
|
||||||
|
(SID_LIST =
|
||||||
|
(SID_DESC =
|
||||||
|
(SID_NAME = PSQLU)
|
||||||
|
(ORACLE_HOME=/opt/oracle/product/19c/dbhome_1)
|
||||||
|
(PROGRAM=dg4odbc)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Y añadimos una entrada de conexión a `/opt/oracle/product/19c/dbhome_1/network/admin/tnsnames.ora`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PSQLU =
|
||||||
|
(DESCRIPTION=
|
||||||
|
(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))
|
||||||
|
(CONNECT_DATA=(SID=PSQLU))
|
||||||
|
(HS=OK)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora reiniciamos el listener y creamos el enlace dentro de oracle.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
create database link postgreslink connect to "roberto" identified by"roberto" using 'PSQLU';
|
||||||
|
```
|
||||||
|
|
||||||
|
Ya está creado el enlace. Ahora para comprobar que funciona, podemos hacer una consulta:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT "ename" FROM "emp"@postgreslink;
|
||||||
|
```
|
||||||
|
|
||||||
|
![6](https://i.imgur.com/rSga9bn.png)
|
After Width: | Height: | Size: 198 KiB |
@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
title: "Compilación Kernel"
|
||||||
|
date: 2022-12-07T21:18:17+01:00
|
||||||
|
draft: false
|
||||||
|
image: featured.png
|
||||||
|
categories:
|
||||||
|
- documentación
|
||||||
|
- Administración de Sistemas Operativos
|
||||||
|
tags:
|
||||||
|
- Compilación
|
||||||
|
- Debian
|
||||||
|
---
|
||||||
|
|
||||||
|
## Compilación de un Kernel linux a medida
|
||||||
|
|
||||||
|
Al ser linux un kérnel libre, es posible descargar el código fuente, configurarlo y comprimirlo. Además, esta tarea a priori compleja, es más sencilla de lo que parece gracias a las herramientas disponibles.
|
||||||
|
En esta tarea debes tratar de compilar un kérnel completamente funcional que reconozca todo el hardware básico de tu equipo y que sea a la vez lo más pequeño posible, es decir que incluya un vmlinuz lo más pequeño posible y que incorpore sólo los módulos imprescindibles. Para ello utiliza el método explicado en clase y entrega finalmente el fichero deb con el kérnel compilado por ti.
|
||||||
|
El hardware básico incluye como mínimo el teclado, la interfaz de red y la consola gráfica (texto).
|
||||||
|
|
||||||
|
## Descarga
|
||||||
|
|
||||||
|
En este caso vamos a descargar el último kernel de linux de la [página oficial](https://kernel.org/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.0.7.tar.xz
|
||||||
|
tar xf linux-6.0.7.tar.xz
|
||||||
|
cd linux-6.0.7
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compilación del kernel
|
||||||
|
|
||||||
|
Para configurar los módulos que tenemos cargados actualmente en el sistema tenemos que introducir losa siguientes comandos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make oldconfig
|
||||||
|
make localyesconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
Con lo siguiente podemos comprobar el número de módulos estáticos y dinámicos que tenemos actualmente:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
egrep '=y' .config | wc -l
|
||||||
|
egrep '=m' .config | wc -l
|
||||||
|
```
|
||||||
|
|
||||||
|
Para compilar el kernel, tenemos que ejecutar el siguiente comando, que aprovecha el número de núcleos que tenemos para reducir al máximo el tiempo de compilación:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
time make -j $(nproc) bindeb-pkg
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reducir el kernel
|
||||||
|
|
||||||
|
Para reducir el tamaño del kernel tenemos que desactivar módulos. Éstos se desactivan ejecutando el siguiente comando:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make clean
|
||||||
|
make xconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
que abre una interfaz gráfica en la que podemos seleccionar los módulos quq queremos activar o desactivar:
|
||||||
|
|
||||||
|
![https://i.imgur.com/cndWKk6.png](https://i.imgur.com/cndWKk6.png)
|
||||||
|
|
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 168 KiB |
@ -0,0 +1,421 @@
|
|||||||
|
---
|
||||||
|
title: "Práctica PL/SQL individual"
|
||||||
|
date: 2022-12-07T13:37:02+01:00
|
||||||
|
draft: false
|
||||||
|
image: featured.png
|
||||||
|
categories:
|
||||||
|
- documentación
|
||||||
|
- Administración de Bases de Datos
|
||||||
|
tags:
|
||||||
|
- Oracle
|
||||||
|
- PL/SQL
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hacer un procedimiento que muestre el nombre y el salario del empleado cuyo código es 7782
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE mostrarnombresalario
|
||||||
|
is
|
||||||
|
v_nombre emp.ename%type;
|
||||||
|
v_salario emp.sal%type;
|
||||||
|
begin
|
||||||
|
select ename,sal into v_nombre,v_salario from emp where empno=7782;
|
||||||
|
dbms_output.put_line('El nombre del empleado es ' || v_nombre || ' y su salario es: ' || v_salario);
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p1](https://i.imgur.com/CscMTfL.png)
|
||||||
|
|
||||||
|
## Hacer un procedimiento que reciba como parámetro un código de empleado y devuelva su nombre
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE mostrarnombresalario2 (p_empno emp.empno%TYPE)
|
||||||
|
is
|
||||||
|
v_nombre emp.ename%type;
|
||||||
|
v_salario emp.sal%type;
|
||||||
|
begin
|
||||||
|
select ename,sal into v_nombre,v_salario from emp where empno=p_empno;
|
||||||
|
dbms_output.put_line('El nombre del empleado es ' || v_nombre || ' y su salario es: ' || v_salario);
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p2](https://i.imgur.com/o2tqMaP.png)
|
||||||
|
|
||||||
|
## Hacer un procedimiento que devuelva los nombres de los tres empleados más antiguos
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE topantiguos
|
||||||
|
is
|
||||||
|
cursor c_top is
|
||||||
|
select ename
|
||||||
|
from emp
|
||||||
|
order by hiredate asc
|
||||||
|
fetch first 3 rows only;
|
||||||
|
begin
|
||||||
|
dbms_output.put_line('Los 3 empleados mas antiguos son: ');
|
||||||
|
for v_empleado in c_top loop
|
||||||
|
dbms_output.put_line(v_empleado.ename);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p3](https://i.imgur.com/FOSjg5a.png)
|
||||||
|
|
||||||
|
## Hacer un procedimiento que reciba el nombre de un tablespace y muestre los nombres de los usuarios que lo tienen como tablespace por defecto (Vista DBA_USERS)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE verusuarios (p_tablespace dba_users.default_tablespace%type)
|
||||||
|
is
|
||||||
|
cursor c_usuarios is
|
||||||
|
SELECT username
|
||||||
|
from dba_users
|
||||||
|
where default_tablespace=p_tablespace;
|
||||||
|
begin
|
||||||
|
dbms_output.put_line('El tablespace ' || p_tablespace || ' es el predeterminado de los siguientes usuarios:');
|
||||||
|
for v_usuario in c_usuarios loop
|
||||||
|
dbms_output.put_line(v_usuario.username);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p4](https://i.imgur.com/U3oRByX.png)
|
||||||
|
|
||||||
|
## Modificar el procedimiento anterior para que haga lo mismo pero devolviendo el número de usuarios que tienen ese tablespace como tablespace por defecto. Nota: Hay que convertir el procedimiento en función
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE function f_numusuarios (p_tablespace dba_users.default_tablespace%type)
|
||||||
|
return number
|
||||||
|
is
|
||||||
|
v_num number;
|
||||||
|
begin
|
||||||
|
select count(username) into v_num from dba_users where default_tablespace=p_tablespace;
|
||||||
|
return v_num;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hacer un procedimiento llamado mostrar_usuarios_por_tablespace que muestre por pantalla un listado de los tablespaces existentes con la lista de usuarios de cada uno y el número de los mismos, así: (Vistas DBA_TABLESPACES y DBA_USERS)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
Tablespace xxxx:
|
||||||
|
|
||||||
|
Usr1
|
||||||
|
Usr2
|
||||||
|
...
|
||||||
|
|
||||||
|
Total Usuarios Tablespace xxxx: n1
|
||||||
|
|
||||||
|
Tablespace yyyy:
|
||||||
|
|
||||||
|
Usr1
|
||||||
|
Usr2
|
||||||
|
...
|
||||||
|
|
||||||
|
Total Usuarios Tablespace yyyy: n2
|
||||||
|
....
|
||||||
|
Total Usuarios BD: nn
|
||||||
|
```
|
||||||
|
|
||||||
|
He modificado el procedimiento del ejercicio 4:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE verusuarios (p_tablespace dba_users.default_tablespace%type)
|
||||||
|
is
|
||||||
|
cursor c_usuarios is
|
||||||
|
SELECT username
|
||||||
|
from dba_users
|
||||||
|
where default_tablespace=p_tablespace;
|
||||||
|
begin
|
||||||
|
for v_usuario in c_usuarios loop
|
||||||
|
dbms_output.put_line(CHR(9)|| v_usuario.username);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
Y el procedimiento nuevo es:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE mostrar_usuarios_por_tablespace
|
||||||
|
is
|
||||||
|
cursor c_tablespaces is
|
||||||
|
SELECT tablespace_name
|
||||||
|
from dba_tablespaces;
|
||||||
|
v_total_usuario number;
|
||||||
|
v_total number:=0;
|
||||||
|
begin
|
||||||
|
for v_tablespace in c_tablespaces loop
|
||||||
|
dbms_output.put_line('Tablespace ' || v_tablespace.tablespace_name);
|
||||||
|
verusuarios(v_tablespace.tablespace_name);
|
||||||
|
v_total_usuario:=f_numusuarios(v_tablespace.tablespace_name);
|
||||||
|
v_total:=v_total+v_total_usuario;
|
||||||
|
dbms_output.put_line('Total Usuarios tablespace ' || v_tablespace.tablespace_name || ': ' || v_total_usuario);
|
||||||
|
end loop;
|
||||||
|
dbms_output.put_line('Total Usuarios BD : ' || v_total);
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p5](https://i.imgur.com/1sCHBpU.png)
|
||||||
|
|
||||||
|
[...]
|
||||||
|
|
||||||
|
![p6](https://i.imgur.com/pbjFtsP.png)
|
||||||
|
|
||||||
|
## Hacer un procedimiento llamado mostrar_codigo_fuente que reciba el nombre de otro procedimiento y muestre su código fuente. (DBA_SOURCE)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE mostrar_codigo_fuente (p_nombre dba_source.name%type)
|
||||||
|
is
|
||||||
|
cursor c_codigo is
|
||||||
|
SELECT text
|
||||||
|
from dba_source
|
||||||
|
where name=p_nombre;
|
||||||
|
begin
|
||||||
|
for v_codigo in c_codigo loop
|
||||||
|
dbms_output.put_line(v_codigo.text);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p7](https://i.imgur.com/zx9BQyp.png)
|
||||||
|
|
||||||
|
## Hacer un procedimiento llamado mostrar_privilegios_usuario que reciba el nombre de un usuario y muestre sus privilegios de sistema y sus privilegios sobre objetos. (DBA_SYS_PRIVS y DBA_TAB_PRIVS)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE mostrar_privilegios_usuario (p_nombre dba_source.name%type)
|
||||||
|
is
|
||||||
|
cursor c_sistema is
|
||||||
|
SELECT privilege
|
||||||
|
from dba_sys_privs
|
||||||
|
where grantee=p_nombre
|
||||||
|
and ADMIN_OPTION='YES'
|
||||||
|
OR INHERITED='YES';
|
||||||
|
cursor c_objetos is
|
||||||
|
SELECT privilege,table_name
|
||||||
|
from dba_tab_privs
|
||||||
|
where grantee=p_nombre;
|
||||||
|
begin
|
||||||
|
dbms_output.put_line('Privilegios del usuario '|| p_nombre || ' de sistema');
|
||||||
|
for v_sistema in c_sistema loop
|
||||||
|
dbms_output.put_line(CHR(9)||v_sistema.privilege);
|
||||||
|
end loop;
|
||||||
|
dbms_output.put_line('Privilegios del usuario '|| p_nombre || ' sobre objetos');
|
||||||
|
for v_objeto in c_objetos loop
|
||||||
|
dbms_output.put_line(CHR(9)||v_objeto.privilege || '---' || v_objeto.table_name);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p8](https://i.imgur.com/V9bkArM.png)
|
||||||
|
|
||||||
|
## Realiza un procedimiento llamado listar_comisiones que nos muestre por pantalla un listado de las comisiones de los empleados agrupados según la localidad donde está ubicado su departamento con el siguiente formato:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
Localidad NombreLocalidad
|
||||||
|
|
||||||
|
Departamento: NombreDepartamento
|
||||||
|
|
||||||
|
Empleado1 ……. Comisión 1
|
||||||
|
Empleado2 ……. Comisión 2
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
Empleadon ……. Comision n
|
||||||
|
|
||||||
|
Total Comisiones en el Departamento NombreDepartamento: SumaComisiones
|
||||||
|
|
||||||
|
Departamento: NombreDepartamento
|
||||||
|
|
||||||
|
Empleado1 ……. Comisión 1
|
||||||
|
Empleado2 ……. Comisión 2
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
Empleadon ……. Comision n
|
||||||
|
|
||||||
|
Total Comisiones en el Departamento NombreDepartamento: SumaComisiones
|
||||||
|
.
|
||||||
|
.
|
||||||
|
Total Comisiones en la Localidad NombreLocalidad: SumaComisionesLocalidad
|
||||||
|
|
||||||
|
Localidad NombreLocalidad
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
Total Comisiones en la Empresa: TotalComisiones
|
||||||
|
```
|
||||||
|
|
||||||
|
Nota: Los nombres de localidades, departamentos y empleados deben aparecer por orden alfabético.
|
||||||
|
|
||||||
|
Si alguno de los departamentos no tiene ningún empleado con comisiones, aparecerá un mensaje informando de ello en lugar de la lista de empleados.
|
||||||
|
|
||||||
|
El procedimiento debe gestionar adecuadamente las siguientes excepciones:
|
||||||
|
|
||||||
|
a) La tabla Empleados está vacía.
|
||||||
|
b) Alguna comisión es mayor que 10000.
|
||||||
|
|
||||||
|
He creado dos funciones y un procedimiento:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE FUNCTION listar_empleados(p_deptno dept.deptno%type)
|
||||||
|
return number
|
||||||
|
is
|
||||||
|
cursor c_empleados is
|
||||||
|
SELECT ename,comm
|
||||||
|
from emp
|
||||||
|
where deptno=p_deptno
|
||||||
|
order by ename;
|
||||||
|
v_vacio number;
|
||||||
|
v_suma number:=0;
|
||||||
|
v_valor number;
|
||||||
|
begin
|
||||||
|
select sum(comm) into v_vacio from emp where deptno=p_deptno;
|
||||||
|
if v_vacio>0 then
|
||||||
|
for v_empleado in c_empleados loop
|
||||||
|
IF v_empleado.comm is NULL THEN
|
||||||
|
v_valor:=0;
|
||||||
|
ELSE
|
||||||
|
v_suma:=v_suma+v_empleado.comm;
|
||||||
|
v_valor:=v_empleado.comm;
|
||||||
|
END IF;
|
||||||
|
dbms_output.put_line(CHR(9)||CHR(9)|| v_empleado.ename || ' ... ' || v_valor);
|
||||||
|
end loop;
|
||||||
|
else
|
||||||
|
dbms_output.put_line(CHR(9)||CHR(9)|| 'El departamento no tiene comisiones');
|
||||||
|
end if;
|
||||||
|
return v_suma;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN NO_DATA_FOUND then
|
||||||
|
dbms_output.put_line('La tabla empleados está vacía');
|
||||||
|
return 0;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION listar_departamentos(p_loc dept.loc%type)
|
||||||
|
return number
|
||||||
|
is
|
||||||
|
cursor c_departamentos is
|
||||||
|
SELECT dname,deptno
|
||||||
|
from dept
|
||||||
|
where loc=p_loc
|
||||||
|
order by dname;
|
||||||
|
v_total number;
|
||||||
|
v_suma number:=0;
|
||||||
|
begin
|
||||||
|
for v_departamento in c_departamentos loop
|
||||||
|
dbms_output.put_line(CHR(9)|| 'Departamento: ' || v_departamento.dname);
|
||||||
|
v_total:=listar_empleados(v_departamento.deptno);
|
||||||
|
dbms_output.put_line(CHR(9)|| 'Total Comisiones en el Departamento ' || v_departamento.dname || ': ' || v_total);
|
||||||
|
v_suma:=v_suma+v_total;
|
||||||
|
end loop;
|
||||||
|
return v_suma;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE listar_comisiones
|
||||||
|
is
|
||||||
|
cursor c_localidades is
|
||||||
|
SELECT loc
|
||||||
|
from dept
|
||||||
|
order by loc;
|
||||||
|
v_total number;
|
||||||
|
v_suma number:=0;
|
||||||
|
begin
|
||||||
|
for v_localidad in c_localidades loop
|
||||||
|
dbms_output.put_line('Localidad ' || v_localidad.loc);
|
||||||
|
v_total:=listar_departamentos(v_localidad.loc);
|
||||||
|
dbms_output.put_line('Total Comisiones en la Localidad ' || v_localidad.loc || ': ' || v_total);
|
||||||
|
v_suma:=v_suma+v_total;
|
||||||
|
end loop;
|
||||||
|
dbms_output.put_line('Total Comisiones de la Empresa ' || v_suma);
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
![p9](https://i.imgur.com/DGWQS1b.png)
|
||||||
|
|
||||||
|
## . Realiza un procedimiento que reciba el nombre de una tabla y muestre los nombres de las restricciones que tiene, a qué columna afectan y en qué consisten exactamente. (DBA_TABLES, DBA_CONSTRAINTS, DBA_CONS_COLUMNS)
|
||||||
|
|
||||||
|
He realizado los siguientes procedimientos:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PROCEDURE listar_restriccion(p_nombre user_constraints.table_name%type,p_tabla user_constraints.table_name%type)
|
||||||
|
is
|
||||||
|
v_tipo user_constraints.constraint_type%type;
|
||||||
|
v_nombre user_constraints.constraint_name%type;
|
||||||
|
v_referencia user_constraints.r_constraint_name%type;
|
||||||
|
v_condicion user_constraints.search_condition%type;
|
||||||
|
begin
|
||||||
|
select constraint_name,constraint_type,r_constraint_name,search_condition into v_nombre,v_tipo,v_referencia,v_condicion
|
||||||
|
from user_constraints
|
||||||
|
where table_name = p_tabla
|
||||||
|
and constraint_name=p_nombre;
|
||||||
|
if v_tipo='P' then
|
||||||
|
dbms_output.put_line(p_nombre || ' ... es de tipo CLAVE PRIMARIA');
|
||||||
|
elsif v_tipo='R' then
|
||||||
|
dbms_output.put_line(p_nombre || ' ... es de tipo CLAVE EXTERNA y hace referencia a: ' || v_nombre);
|
||||||
|
elsif v_tipo='C' then
|
||||||
|
dbms_output.put_line(p_nombre || ' ... es de tipo CHECK y contiene la siguiente comprobacion: ' || v_condicion);
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE listar_restricciones(p_tabla user_constraints.table_name%type)
|
||||||
|
is
|
||||||
|
cursor c_columnas is
|
||||||
|
SELECT constraint_name,column_name
|
||||||
|
from user_cons_columns
|
||||||
|
where table_name=p_tabla;
|
||||||
|
begin
|
||||||
|
dbms_output.put_line('Restricciones de la tabla ' || p_tabla);
|
||||||
|
for v_columna in c_columnas loop
|
||||||
|
listar_restriccion(v_columna.constraint_name,p_tabla);
|
||||||
|
dbms_output.put_line(CHR(9)||'Hace referencia a la columna -> ' || v_columna.column_name);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
En la comprobación introduzco una tabla diferente al esquema SCOTT ya que tiene más restricciones:
|
||||||
|
|
||||||
|
![p10](https://i.imgur.com/OMoSRQz.png)
|
||||||
|
|
||||||
|
## Realiza al menos dos de los ejercicios anteriores en Postgres usando PL/pgSQL.
|
||||||
|
|
||||||
|
## Ejercicio 1
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE or replace PROCEDURE mostrarnombresalario() AS $$
|
||||||
|
DECLARE
|
||||||
|
v_nombre emp.ename%type;
|
||||||
|
v_salario emp.sal%type;
|
||||||
|
BEGIN
|
||||||
|
select ename,sal into v_nombre,v_salario from emp where empno=7782;
|
||||||
|
RAISE NOTICE 'El nombre del empleado es %, y su salario es %', v_nombre,v_salario;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
```
|
||||||
|
|
||||||
|
![p11](https://i.imgur.com/GifaOGt.png)
|
||||||
|
|
||||||
|
## Ejercicio 2
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE or replace PROCEDURE mostrarnombresalario2(p_empno emp.empno%type) AS $$
|
||||||
|
DECLARE
|
||||||
|
v_nombre emp.ename%type;
|
||||||
|
BEGIN
|
||||||
|
select ename into v_nombre from emp where empno=7782;
|
||||||
|
RAISE NOTICE 'El nombre del empleado cuyo codigo es %, es %', p_empno,v_nombre;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
```
|
||||||
|
|
||||||
|
![p12](https://i.imgur.com/OKfLC2X.png)
|
After Width: | Height: | Size: 198 KiB |
@ -0,0 +1,122 @@
|
|||||||
|
---
|
||||||
|
title: "Montaje NFS mediante systemd"
|
||||||
|
date: 2022-12-15T13:24:40+01:00
|
||||||
|
draft: false
|
||||||
|
image: featured.png
|
||||||
|
categories:
|
||||||
|
- documentación
|
||||||
|
- Administración de Sistemas Operativos
|
||||||
|
tags:
|
||||||
|
- NFS
|
||||||
|
- Openstack
|
||||||
|
- Debian
|
||||||
|
---
|
||||||
|
|
||||||
|
En una instancia del cloud, basada en la distribución de tu elección, anexa un volumen de 2GB. En dicha instancia deberás configurar el servicio nfs de exportación y en el volumen un punto de montaje de la exportación mediante systemd.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Escenario
|
||||||
|
|
||||||
|
El escenario se compone de dos máquinas, alfa, con debian 11 y que será el servidor nfs; y bravo, con rocky linux 8 y que será el cliente nfs.
|
||||||
|
|
||||||
|
## Servidor NFS
|
||||||
|
|
||||||
|
Instalamos los paquetes necesarios para el servicio nfs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install nfs-kernel-server nfs-common
|
||||||
|
```
|
||||||
|
|
||||||
|
Creamos el fichero `/etc/systemd/system/mnt-carpeta.mount` con el siguiente contenido. El nombre del fichero, tiene que ser el mismo que el del punto de montaje en el que vamos a montar el dispositivo, además de sustituyendo las "/" por "-" (menos la primera):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[Unit]
|
||||||
|
Description=Montaje de disco para compartir
|
||||||
|
|
||||||
|
[Mount]
|
||||||
|
What= /dev/vdb
|
||||||
|
Where= /mnt/carpeta/
|
||||||
|
Type=ext4
|
||||||
|
Options=defaults
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
Activamos el servicio:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl enable mnt-carpeta.mount
|
||||||
|
systemctl start mnt-carpeta.mount
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Si no funciona el montaje de la unidad, podemos comprobar os errores con `journalctl -xe`
|
||||||
|
|
||||||
|
Tras el montaje podemos comprobar que el disco se ha montado correctamente:
|
||||||
|
|
||||||
|
![Montaje de disco](https://i.imgur.com/8cUkODO.png)
|
||||||
|
|
||||||
|
Finalmente, añadimos la siguiente línea al fichero `/etc/exports`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/mnt/carpeta 172.16.0.0/16(rw,no_all_squash,no_subtree_check)
|
||||||
|
```
|
||||||
|
|
||||||
|
Y reiniciamos el servicio:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl restart nfs-server
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Cliente NFS
|
||||||
|
|
||||||
|
Instalamos los paquetes necesarios para el servicio nfs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dnf install nfs-utils
|
||||||
|
```
|
||||||
|
|
||||||
|
Podemos ver los dispositivos de bloques que se están compartiendo por nfs (la ip del servidor nfs es `172.16.0.1`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
showmount -e 172.16.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
![Dispositivos compartidos](https://i.imgur.com/oaYEhYA.png)
|
||||||
|
|
||||||
|
Creamos el fichero `/etc/systemd/system/mnt-carpetaNFS.mount` con el siguiente contenido:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[Unit]
|
||||||
|
Description=Montaje del disco compartido por red usando NFS
|
||||||
|
|
||||||
|
[Mount]
|
||||||
|
What=172.16.0.1:/mnt/carpeta
|
||||||
|
Where=/mnt/carpetaNFS
|
||||||
|
Type=nfs
|
||||||
|
Options=defaults
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
Activamos el servicio:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl enable mnt-carpetaNFS.mount
|
||||||
|
systemctl start mnt-carpetaNFS.mount
|
||||||
|
```
|
||||||
|
|
||||||
|
Podemos comprobar que el disco se ha montado correctamente:
|
||||||
|
|
||||||
|
![Montaje de disco 2](https://i.imgur.com/l4fEpSh.png)
|
||||||
|
|
||||||
|
## Comprobación
|
||||||
|
|
||||||
|
Comprobamos que el dispositivo de bloques se está compartiendo por nfs:
|
||||||
|
|
||||||
|
![Comprobación](https://i.imgur.com/16NCruU.png)
|
||||||
|
|
After Width: | Height: | Size: 118 KiB |
@ -0,0 +1,213 @@
|
|||||||
|
---
|
||||||
|
title: "Escenario Dns"
|
||||||
|
date: 2022-12-19T14:01:03+01:00
|
||||||
|
draft: false
|
||||||
|
image: featured.png
|
||||||
|
categories:
|
||||||
|
- práctica
|
||||||
|
- Servicios de Red e Internet
|
||||||
|
tags:
|
||||||
|
- DNS
|
||||||
|
- Openstack
|
||||||
|
- bind9
|
||||||
|
---
|
||||||
|
|
||||||
|
El enunciado de la prácica se encuentra en el siguiente [enlace](https://fp.josedomingo.org/sri2223/5_dns/practica.html)
|
||||||
|
|
||||||
|
## 1. Configuración DNS de cada máquina
|
||||||
|
|
||||||
|
Para no tocar la configuración de los servidores DHCP de **OpenStack**, cambiamos manualmente la configuración de las máquinas **Alfa, Bravo y Delta** para que tengan como servidor DNS el servidor **bind9** en **Charlie**, así como el dns del centro (Babuino). Para ello, editamos el fichero `/etc/resolv.conf` y añadimos las siguientes líneas:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nameserver 192.168.0.2
|
||||||
|
nameserver 192.168.202.2
|
||||||
|
```
|
||||||
|
|
||||||
|
Para hacer los cambios persistentes en debian/ubuntu, instalamos el paquete `resolvconf`y añadimos los dns al final del fichero `/etc/resolvconf/resolv.conf.d/head`. Para aplicar los cambios sin tener que reiniciar tenemos que ejecutar el comando `resolvconf -u`.
|
||||||
|
|
||||||
|
#### VISTAS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
view interna {
|
||||||
|
match-clients { 192.168.0.0/24; 127.0.0.1; };
|
||||||
|
allow-recursion { any; };
|
||||||
|
zone "roberto.gonzalonazareno.org"
|
||||||
|
{
|
||||||
|
type master;
|
||||||
|
file "db.interna.roberto.gonzalonazareno.org";
|
||||||
|
};
|
||||||
|
zone "0.168.192.in-addr.arpa"
|
||||||
|
{
|
||||||
|
type master;
|
||||||
|
file "db.0.168.192";
|
||||||
|
};
|
||||||
|
zone "16.172.in-addr.arpa"
|
||||||
|
{
|
||||||
|
type master;
|
||||||
|
file "db.0.16.172";
|
||||||
|
};
|
||||||
|
include "/etc/bind/zones.rfc1918";
|
||||||
|
include "/etc/bind/named.conf.default-zones";
|
||||||
|
};
|
||||||
|
|
||||||
|
view dmz {
|
||||||
|
match-clients { 172.16.0/16;};
|
||||||
|
allow-recursion { any; };
|
||||||
|
zone "roberto.gonzalonazareno.org"
|
||||||
|
{
|
||||||
|
type master;
|
||||||
|
file "db.dmz.roberto.gonzalonazareno.org";
|
||||||
|
};
|
||||||
|
zone "16.172.in-addr.arpa"
|
||||||
|
{
|
||||||
|
type master;
|
||||||
|
file "db.16.172";
|
||||||
|
};
|
||||||
|
include "/etc/bind/zones.rfc1918";
|
||||||
|
include "/etc/bind/named.conf.default-zones";
|
||||||
|
};
|
||||||
|
|
||||||
|
view externa {
|
||||||
|
match-clients { 172.22.0.0/16; 172.29.0.0/16; 192.168.202.2; };
|
||||||
|
allow-recursion { any; };
|
||||||
|
zone "roberto.gonzalonazareno.org"
|
||||||
|
{
|
||||||
|
type master;
|
||||||
|
file "db.externa.roberto.gonzalonazareno.org";
|
||||||
|
};
|
||||||
|
include "/etc/bind/zones.rfc1918";
|
||||||
|
include "/etc/bind/named.conf.default-zones";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Definición de las zonas
|
||||||
|
|
||||||
|
### INTERNA /var/cache/bind/db.interna.roberto.gonzalonazareno.org
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$TTL 86400
|
||||||
|
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||||
|
1 ; Serial
|
||||||
|
604800 ; Refresh
|
||||||
|
86400 ; Retry
|
||||||
|
2419200 ; Expire
|
||||||
|
86400 ) ; Negative Cache TTL
|
||||||
|
;
|
||||||
|
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||||
|
@ IN MX 10 mail.roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
$ORIGIN roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
alfa IN A 192.168.0.1
|
||||||
|
bravo IN A 172.16.0.200
|
||||||
|
charlie IN A 192.168.0.2
|
||||||
|
delta IN A 192.168.0.3
|
||||||
|
www IN CNAME bravo
|
||||||
|
bd IN CNAME delta
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### INTERNA INVERSA /var/cache/bind/db.0.168.192
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$TTL 86400
|
||||||
|
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||||
|
1 ; Serial
|
||||||
|
604800 ; Refresh
|
||||||
|
86400 ; Retry
|
||||||
|
2419200 ; Expire
|
||||||
|
86400 ) ; Negative Cache TTL
|
||||||
|
;
|
||||||
|
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
$ORIGIN 0.168.192.in-addr.arpa.
|
||||||
|
|
||||||
|
1 IN PTR alfa.roberto.gonzalonazareno.org.
|
||||||
|
2 IN PTR charlie.roberto.gonzalonazareno.org.
|
||||||
|
3 IN PTR delta.roberto.gonzalonazareno.org.
|
||||||
|
```
|
||||||
|
|
||||||
|
### INTERNA INVERSA /var/cache/bind/db.16.172
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$TTL 86400
|
||||||
|
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||||
|
1 ; Serial
|
||||||
|
604800 ; Refresh
|
||||||
|
86400 ; Retry
|
||||||
|
2419200 ; Expire
|
||||||
|
86400 ) ; Negative Cache TTL
|
||||||
|
;
|
||||||
|
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
$ORIGIN 16.172.in-addr.arpa.
|
||||||
|
|
||||||
|
1.0 IN PTR alfa.roberto.gonzalonazareno.org.
|
||||||
|
200.0 IN PTR bravo.roberto.gonzalonazareno.org.
|
||||||
|
```
|
||||||
|
|
||||||
|
### DMZ /var/cache/bind/db.dmz.roberto.gonzalonazareno.org
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$TTL 86400
|
||||||
|
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||||
|
1 ; Serial
|
||||||
|
604800 ; Refresh
|
||||||
|
86400 ; Retry
|
||||||
|
2419200 ; Expire
|
||||||
|
86400 ) ; Negative Cache TTL
|
||||||
|
;
|
||||||
|
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
$ORIGIN roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
alfa IN A 172.16.0.1
|
||||||
|
bravo IN A 172.16.0.200
|
||||||
|
charlie IN A 192.168.0.2
|
||||||
|
delta IN A 192.168.0.3
|
||||||
|
www IN CNAME bravo
|
||||||
|
bd IN CNAME delta
|
||||||
|
```
|
||||||
|
|
||||||
|
### EXTERNA /var/cache/bind/db.externa.roberto.gonzalonazareno.org
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$TTL 86400
|
||||||
|
@ IN SOA alfa.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||||
|
1 ; Serial
|
||||||
|
604800 ; Refresh
|
||||||
|
86400 ; Retry
|
||||||
|
2419200 ; Expire
|
||||||
|
86400 ) ; Negative Cache TTL
|
||||||
|
;
|
||||||
|
@ IN NS alfa.roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
$ORIGIN roberto.gonzalonazareno.org.
|
||||||
|
|
||||||
|
alfa IN A 172.22.200.218
|
||||||
|
www IN CNAME alfa
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Configuración de los servidores web
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName www.roberto.gonzalonazareno.org
|
||||||
|
|
||||||
|
ServerAdmin webmaster@localhost
|
||||||
|
|
||||||
|
DocumentRoot /var/www/html
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||||
|
|
||||||
|
<FilesMatch "\.php$">
|
||||||
|
SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://127.0.0.1/"
|
||||||
|
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
||||||
|
```
|
After Width: | Height: | Size: 168 KiB |
@ -0,0 +1,177 @@
|
|||||||
|
---
|
||||||
|
title: "Resolución de problemas de
|
||||||
|
tablas mutantes"
|
||||||
|
date: 2022-12-19T00:51:41+01:00
|
||||||
|
draft: false
|
||||||
|
image: featured.png
|
||||||
|
categories:
|
||||||
|
- documentación
|
||||||
|
- Administración de Bases de Datos
|
||||||
|
tags:
|
||||||
|
- tablas mutantes
|
||||||
|
- Oracle
|
||||||
|
- PL/SQL
|
||||||
|
---
|
||||||
|
|
||||||
|
El enunciado a resolver y que contiene una tabla mutante es el siguiente:
|
||||||
|
|
||||||
|
**6 - Realiza los módulos de programación necesarios para evitar que un catador puntue más de tres aspectos de una misma versión de un experimento.**
|
||||||
|
|
||||||
|
En este caso, el trigger principal sería sobre la tabla puntuaciones, y dentro, para comprobar que se cumple la condición de que un catador no puntúa más de 3 aspectos, se tendría que hacer una consulta a la misma tabla puntuaciones, que en ese caso estaría mutando. Para resolver el problema vamos a realizar los siguientes pasos:
|
||||||
|
|
||||||
|
1. Leer bien los requisitos del problema e identificar la
|
||||||
|
información de la tabla que debo guardar en variables
|
||||||
|
persistentes.
|
||||||
|
2. Crear el paquete declarando los tipos de datos y las variables
|
||||||
|
necesarias para guardar dicha información.
|
||||||
|
3. Hacer un trigger before por sentencia que rellene dichas
|
||||||
|
variables consultando la tabla mutante.
|
||||||
|
4. Hacer un trigger before por fila que compruebe si el registro
|
||||||
|
que se está manejando cumple la condición especificada
|
||||||
|
consultando las variables persistentes.
|
||||||
|
|
||||||
|
## Leer bien los requisitos del problema e identificar la información de la tabla que debo guardar en variables persistentes
|
||||||
|
|
||||||
|
El contenido de la tabla de puntuaciones es el siguiente:
|
||||||
|
|
||||||
|
![Tabla puntuaciones](https://i.imgur.com/wMxNzMj.png)
|
||||||
|
|
||||||
|
En este caso, tendríamos que almacenar en variables persistentes los datos de la consulta, que en este caso son los siguientes campos:
|
||||||
|
|
||||||
|
* NIFCatador
|
||||||
|
* CodigoAspecto
|
||||||
|
* CodigoExperimento
|
||||||
|
* CodigoVersion
|
||||||
|
|
||||||
|
## Crear el paquete declarando los tipos de datos y las variables necesarias para guardar dicha información
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE PACKAGE ControlPuntuaciones
|
||||||
|
AS
|
||||||
|
TYPE tRegistroTablaPuntuaciones IS RECORD --defino el tipo de datos registro
|
||||||
|
(
|
||||||
|
NIFCatador Puntuaciones.NIFCatador%TYPE,
|
||||||
|
CodigoAspecto Puntuaciones.CodigoAspecto%TYPE,
|
||||||
|
CodigoExperimento Puntuaciones.CodigoExperimento%TYPE,
|
||||||
|
CodigoVersion Puntuaciones.CodigoVersion%TYPE
|
||||||
|
);
|
||||||
|
|
||||||
|
TYPE tTablasPuntuaciones IS TABLE OF tRegistroTablaPuntuaciones -- defino el tipo de datos tabla
|
||||||
|
INDEX BY BINARY_INTEGER;
|
||||||
|
PuntuacionesCatador tTablasPuntuaciones;
|
||||||
|
-- declaro una variable del tipo tabla antes creado
|
||||||
|
END ControlPuntuaciones;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hacer un trigger before por sentencia que rellene dichas variables consultando la tabla mutante
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE TRIGGER RELLENARPUNTUACIONES
|
||||||
|
BEFORE INSERT OR UPDATE ON Puntuaciones
|
||||||
|
FOR EACH ROW
|
||||||
|
DECLARE
|
||||||
|
CURSOR c_puntuaciones IS SELECT NIFCatador,CodigoAspecto,CodigoExperimento,CodigoVersion
|
||||||
|
FROM Puntuaciones;
|
||||||
|
INDICE NUMBER:=0;
|
||||||
|
indice_u number;
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
-- vacio el contenido de la tabla
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador.DELETE;
|
||||||
|
-- relleno la tabla de puntuaciones los datos que me interesan
|
||||||
|
FOR v_puntuacion IN c_puntuaciones LOOP
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(INDICE).NIFCatador := v_puntuacion.NIFCatador;
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(INDICE).CodigoAspecto := v_puntuacion.CodigoAspecto;
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(INDICE).CodigoExperimento := v_puntuacion.CodigoExperimento;
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(INDICE).CodigoVersion := v_puntuacion.CodigoVersion;
|
||||||
|
INDICE := INDICE + 1;
|
||||||
|
END LOOP;
|
||||||
|
if inserting then
|
||||||
|
indice_u := ControlPuntuaciones.PuntuacionesCatador.LAST + 1;
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(indice_u).NIFCatador := :NEW.NIFCatador;
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(indice_u).CodigoAspecto := :NEW.CodigoAspecto;
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(indice_u).CodigoExperimento := :NEW.CodigoExperimento;
|
||||||
|
ControlPuntuaciones.PuntuacionesCatador(indice_u).CodigoVersion := :NEW.CodigoVersion;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
END RELLENARPUNTUACIONES;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hacer un trigger before por fila que compruebe si el registro que se está manejando cumple la condición especificada consultando las variables persistentes
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE TRIGGER ControlarPuntuaciones
|
||||||
|
BEFORE INSERT OR UPDATE ON Puntuaciones
|
||||||
|
FOR EACH ROW
|
||||||
|
DECLARE
|
||||||
|
BEGIN
|
||||||
|
-- compruebo que el catador no haya puntuado más de 3 aspectos
|
||||||
|
IF (NumeroPuntuacionesCatador(:NEW.NIFCatador,:NEW.CodigoExperimento,:NEW.CodigoVersion) > 3) THEN
|
||||||
|
RAISE_APPLICATION_ERROR(-20001,'El catador no puede puntuar mas de 3 aspectos');
|
||||||
|
end if;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
Voy a crear una funcion para comprobar el numero de puntuaciones que tiene un catador en una versión de un experimento:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE OR REPLACE FUNCTION NumeroPuntuacionesCatador
|
||||||
|
( p_NIFCatador Puntuaciones.NIFCatador%TYPE, p_CodigoExperimento Puntuaciones.CodigoExperimento%TYPE, p_CodigoVersion Puntuaciones.CodigoVersion%TYPE)
|
||||||
|
RETURN NUMBER
|
||||||
|
IS
|
||||||
|
v_NumeroPuntuaciones NUMBER:= 1;
|
||||||
|
v_cantidad NUMBER;
|
||||||
|
BEGIN
|
||||||
|
for i in ControlPuntuaciones.PuntuacionesCatador.FIRST..ControlPuntuaciones.PuntuacionesCatador.LAST
|
||||||
|
LOOP
|
||||||
|
if (ControlPuntuaciones.PuntuacionesCatador(i).NIFCatador = p_NIFCatador) and (ControlPuntuaciones.PuntuacionesCatador(i).CodigoExperimento = p_CodigoExperimento) and (ControlPuntuaciones.PuntuacionesCatador(i).CodigoVersion = p_CodigoVersion) then
|
||||||
|
v_NumeroPuntuaciones := v_NumeroPuntuaciones + 1;
|
||||||
|
end if;
|
||||||
|
END LOOP;
|
||||||
|
return v_NumeroPuntuaciones;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
|
||||||
|
--- prueba
|
||||||
|
|
||||||
|
create or replace procedure prueba
|
||||||
|
is
|
||||||
|
numero number;
|
||||||
|
begin
|
||||||
|
numero:=NumeroPuntuacionesCatador('14425879A','A0003-A','0.0.2');
|
||||||
|
dbms_output.put_line(numero);
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
insert into puntuaciones values('14425879A','0004','A0003-A','0.0.2',7.5);
|
||||||
|
|
||||||
|
|
||||||
|
create or replace procedure imprimirtabla
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
for i in ControlPuntuaciones.PuntuacionesCatador.FIRST..ControlPuntuaciones.PuntuacionesCatador.LAST
|
||||||
|
LOOP
|
||||||
|
dbms_output.put_line('Registro numero '|| i);
|
||||||
|
dbms_output.put_line('NIFCatador: '|| ControlPuntuaciones.PuntuacionesCatador(i).NIFCatador);
|
||||||
|
dbms_output.put_line('CodigoAspecto: '|| ControlPuntuaciones.PuntuacionesCatador(i).CodigoAspecto);
|
||||||
|
dbms_output.put_line('CodigoExperimento: '|| ControlPuntuaciones.PuntuacionesCatador(i).CodigoExperimento);
|
||||||
|
dbms_output.put_line('CodigoVersion: '|| ControlPuntuaciones.PuntuacionesCatador(i).CodigoVersion);
|
||||||
|
|
||||||
|
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```sql
|
||||||
|
insert into puntuaciones values('14425879A','0004','A0003-A','0.0.2',7.5);
|
||||||
|
insert into puntuaciones values('14425879A','0005','A0003-A','0.0.2',7.5);
|
||||||
|
insert into puntuaciones values('14425879A','0006','A0003-A','0.0.2',7.5);
|
||||||
|
insert into puntuaciones values('14425879A','0007','A0003-A','0.0.2',7.5);
|
||||||
|
select * from puntuaciones where nifcatador='14425879A' and codigoexperimento='A0003-A' and codigoversion='0.0.2';
|
||||||
|
insert into puntuaciones values('14425879A','0005','A0003-A','0.0.1',7.5);
|
||||||
|
```
|
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 304 KiB |
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 233 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 516 KiB After Width: | Height: | Size: 516 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 546 KiB After Width: | Height: | Size: 546 KiB |
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 407 KiB |
Before Width: | Height: | Size: 459 KiB After Width: | Height: | Size: 459 KiB |
Before Width: | Height: | Size: 273 KiB After Width: | Height: | Size: 273 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |