Habilitar consola avanzada en switch HP1910 o HP1920

Los switch HP 1910 o HP1920 traen una consola resumida. Te enseñare como habilitar la consola extendida.

Como habilitar consola avanzada en switch HP 1910 o HP1920

El primer paso es que ingreses por TELNET al switch con el usuario que tengas. Seguido a esto debes ingresar el siguiente comando:

_cmdline-mode on

<HP 1920G Switch>_cmdline-mode on
All commands can be displayed and executed. Continue? [Y/N]y
Please input password:**********************
Warning: Now you enter an all-command mode for developer's testing, some commands may affect operation by wrong use, please carefully use it with our engineer's direction.

Los posibles passwords son:

  • Jinhua1920unauthorized
  • 512900

Estos pasos son obligatorios de hacer cada vez que ingreses, y de la misma forma el password no se puede cambiar, ya que están por código en el firmware.

Otro dato interesante es Jinhua y su relación con HP:

https://en.wikipedia.org/wiki/Jinhua

http://www.oocities.org/thian-j/resume.htm

Habilitar ssh y telnet en switch HP 1920S o similar

Habilitar SSH y Telnet en switch HP 1920S

Normalmente cuando trabajamos configurando nuestros switch es habitual que realicemos los procesos directamente por consola y no por las GUI WEB que traen instaladas. Sin embargo las ediciones S de HP no traen de forma nativa habilitada dicha opción. En esta oportunidad les contaré un pequeño truco para habilitarlos.

Haciendo backup de la configuración activa

El primer paso es ingresar por la interface web y descargar el backup de la configuración activa. Para ello debemos ingresar en:

Maintenance \ Backup and Update Manager y descargar la configuración activa de inicio (startup configuration)


Habilitando Telnet

Luego modificamos la misma con un editor de texto y agregamos justo antes de configure. La siguiente línea:

 ip telnet server enable 

Seguido a este subimos la nueva configuración y reiniciamos nuestro switch. Ahora podemos ingresar por TELNET.

Habilitando SSH

Ya estamos en condiciones de habilitar el SSH. Para ello debemos colocar en una sesión por TELNET los siguientes comandos:

enable
configure
crypto key generate rsa
crypto key generate dsa
exit
ip ssh server enable
ip ssh protocol 2
write memory confirm
quit

Deshabilitando Telnet (opcional)

Si quisiéramos deshabilitar el TELNET:

enable
no ip telnet server enable
write memory confirm
quit

 

 

Espero que les sirva

Encuesta con Asterisk

Polls Cuestionario por IVR para Asterisk

Existen diversas formas de obtener indicadores del servicio prestado. Sin embargo la mejor retroactividad es la que puede brindarte tu propio cliente. Para ello muchas veces es necesario implementar una encuesta de calidad que permite sondear diferentes aspectos del servicio brindado.

En esta oportunidad se trabajo bajo la siguiente plataforma:

  • Elastix 4
  • Asterisk 11.24

El proceso para armarla la misma consiste en:

  • Una BD MYSQL para guardar los resultados
  • Un ID de la instancia que vamos a guardar (normalmente el ID de tu CRM, o el número de llamada ,etc)
  • DialPlan para que Asterisk interprete los pasos que debe llevar el mismo.
  • Una extensión sobre la cúal recae la encuesta (IVR)
  • Tener audios grabados de las preguntas, los saludos y los mensajes de error ante ingresos erróneos.

Primero que nada vamos a entender como funciona:

  1. Primero éxito una comunicación teléfonica entre el cliente y el personal interno.
  2. Se deja al cliente en línea (hold) y el personal interno procede a llamar a la encuesta
  3. La encuesta es un IVR que atiende automáticamente y solicita el ID para almacenar las respuestas enlazadas a este último.
  4. Una vez que el IVR confirmó que recibió bien el parámetro empieza con la encuesta
  5. Segundos antes el personal interno transfiere el cliente que estaba en línea a la extensión de la encuesta que está a punto de comenzar
  6. Toda respuesta por parte del teclado del cliente es recibida y almacenada en la BD MYSQL por parte del IVR

Como es el archivo del DIALPLAN

En la primer parte se define las variables a usar y la conexión a la BD MYSQL:

;----------------------- INICIO DE PARAMETROS DE ENCUESTA
; 2099 IVR Encuesta
; Inicio
exten => 2099,1,Answer                          ; Atiendo
;exten => 2099,n,Wait(1)                                ; Espero 1 Segundo para darle tiempo al SIP
exten => 2099,n(begin),Set(TIMEOUT(digit)=3)    ; Defino parametros de tiempo
exten => 2099,n,Set(TIMEOUT(response)=3)        ; Defino Parametros de tiempo
;exten => 2099,n,Set(CHANNEL(hangup_handler_push)=hangup-sql,2099,1);  SubRutina de Guardar en Base :: cuando el cliente corta no se puede detectar, se descarta
exten => 2099,n,MYSQL(Connect connid 172.15.15.15 usuario clave base_datos) ; Me conecto a la Base de Datos

; Asignacion de Variables
exten => 2099,n,Set(MSGN=custom/ivr-n)  ; Cargo el Mensaje de Num de Expediente
exten => 2099,n,Set(MSG0=custom/ivr-0)  ; Cargo el Mensaje de Bienvenida
exten => 2099,n,Set(MSG1=custom/ivr-1)  ; Cargo la Pregunta 1
exten => 2099,n,Set(MSG2=custom/ivr-2)  ; Cargo la Pregunta 2
exten => 2099,n,Set(MSG3=custom/ivr-3)  ; Cargo la Pregunta 3
exten => 2099,n,Set(MSG4=custom/ivr-4)  ; Cargo la Pregunta 4
exten => 2099,n,Set(MSG5=custom/ivr-5)  ; Cargo la Pregunta 5
exten => 2099,n,Set(MSG6=custom/ivr-6)  ; Cargo la Pregunta 6
exten => 2099,n,Set(MSGError0=custom/ivr-error0)  ; Cargo el error 0
exten => 2099,n,Set(MSGError1=custom/ivr-error1)  ; Cargo el error 1
exten => 2099,n,Set(MSGError2=custom/ivr-error2)  ; Cargo el error 2
exten => 2099,n,Set(MSGEnd=custom/ivr-end)  ; Cargo el Fin de la Encuesta

Luego viene la parte en donde le pregunto al personal interno el ID inicial para almacenar

;-------------- PREGUNTA N de ID ---------------------------------
;Empiezo con la Pregunta del Numero de ID
exten => 2099,n(pregN),Playback(${MSGN})        ; Reproduzco la Pregunta Num de ID
exten => 2099,n,Goto(2099,pregNresp)    ; voy a esperar la respuesta

;Esperando Respuesta1
exten => 2099,n(pregNresp),Read(NUMBEREXP,,5,1)         ; Leo lo que marca el personal Interno: Num de ID
exten => 2099,n,GotoIf($["${NUMBEREXP}" = ""]?pregN); Si la respuesta es nula entonces Pregunto de Nuevo Num de Expediente
;exten => 2099,n,SayNumber(${NUMBEREXP},f)
exten => 2099,n(pregNconf),Read(NUMBER,,1,1)            ; Leo lo que marca el operador: 1 correcto, 0 correguir
exten => 2099,n,GotoIf($[${NUMBER} = 0]?pregN:intro); Si la respuesta es 0 voy a la pregunta 1

Seguido y validado lo anterior le reproduzco la bienvenida al cliente:

; -------------- INTRO -------------------------------------
; Mensaje explicando el funcionamiento de la encuesta
exten => 2099,n(intro),Playback(beep)   ; Reproduzco un Beep
exten => 2099,n,Set(PREFIJO="2019") ; Asigno un prefijo personalizado. Ej: El año
;exten => 2099,n,Set(NUMBEREXP=$[${PREFIJO}~~${NUMBEREXP}])
exten => 2099,n,Wait(3)  ; Espero 3 Segundos
exten => 2099,n,Playback(${MSG0})       ; Reproduzco la intro
exten => 2099,n,Wait(1)
exten => 2099,n,MYSQL(Query consulta0 ${connid} insert into encuestas(ID,IDCRM,Personal,Fecha1,Fecha2,Activo) values (1,${NUMBEREXP},"Mauro",NOW(),NOW(),1)) ; Inserto la$

Luego debería seguir con las “N” preguntas que pueda tener configurado. Y al final reproducir un mensaje de FIN.

Esto es una idea de cómo se puede implementar.

Funciones Analíticas con SQL Server

En los siguientes artículos que iré creando resumiremos el uso de las siguientes funciones analíticas incorporadas a partir de SQL Server 2012

 

Estas son:

CUME_DIST (Transact-SQL) LEAD (Transact-SQL)
FIRST_VALUE (Transact-SQL) PERCENTILE_CONT (Transact-SQL)
LAG (Transact-SQL) PERCENTILE_DISC (Transact-SQL)
LAST_VALUE (Transact-SQL) PERCENT_RANK (Transact-SQL)

Uso de LAG en SQL Server

Dos nuevas funciones analíticas: LAG y LEAD

A partir de la versión 2012 de SQL Server se incorporaron entre otras cosas dos funciones nuevas, que permiten acceder a la fila anterior, o posterior de una consulta.

Algo que anteriormente era imposible, y tocaba solucionar con Tablas Pivot, o usando Self Join

LAG y LEAD

Primero entendamos que hace cada una:

LAG: devuelve el valor (de una columna especificada) que estuvo en la fila anterior.

LEAD: devuelve el valor (de una columna especificada) que estuvo en la fila siguiente.

Mas info:

https://docs.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql

https://docs.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql

 

 

 

 

Filtrar los NULL en SQL Server

Hoy veremos como trabajar con los NULL

Como siempre con un pequeño ejemplo acompañado de su código y sus capturas veremos como trabajar con campos con valores “NULL”

Creando una tabla de ejemplo

IF EXISTS(SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('myTable'))
BEGIN;
    DROP TABLE [myTable];
END;
GO

CREATE TABLE [myTable] (
    [myTableID] INTEGER NOT NULL IDENTITY(1, 1),
    [nombre] VARCHAR(255) NULL,
    [zona] VARCHAR(MAX) NULL,
    PRIMARY KEY ([myTableID])
);
GO

INSERT INTO myTable([nombre],[zona]) VALUES('Levi','MZA'),('Lars','MZA'),('Lee','CBA'),('Tarik',NULL),('Herman',NULL),('Allen',NULL),('George',NULL),('Ciaran',NULL),('Eagan',NULL),('Drake',NULL);

Resultado del script

Esto nos creará una tabla con la siguiente información:

select * from myTable

trabajando con NULL en SQL Server

Filtrando de manera correcta los NULLs

select * from myTable where zona=NULL
--Versus
select * from myTable where zona IS NULL

Este pequeño ejemplo demuestra como filtrar los NULL mediante el operador IS

filtando valores NULL en SQL ServerEl segundo ejemplo es como debemos filtrar los campos con valores NULL

Para terminar con el ejemplo, si tuviésemos que buscar los registros cuyo columna ZONA no contiene valores nulos (NOT NULL). Para ello podríamos realizar lo siguiente:

select * from myTable where zona is NOT NULL

 

Realizar backup con TSQL

Realizar backup de tus bases con TSQL en MS SQL Server

Hoy veremos una manera simple de realizar un respaldo de todas nuestras bases de datos mediante un pequeño script.

Script para Backup

--------------------------------------------------
--Variables
DECLARE @Base_Datos VARCHAR(50) -- Nombre de la Base de Datos  
DECLARE @Ruta_Archivos VARCHAR(256) -- Ruta para los archivos 
DECLARE @Nombre_A VARCHAR(256) -- Nombre del Backup  (1era Parte)
DECLARE @Nombre_B VARCHAR(20) --  Nombre del Backup (2da Parte)
 
-- 1-Ubicación de los backups
SET @Ruta_Archivos = 'C:\Temp\'  
 
-- Nombre del Archivo (2da Parte) _YYYYMMDD
SELECT @Nombre_B = (SELECT '_'+CONVERT(VARCHAR(20),GETDATE(),112) +'.BAK') 
 
DECLARE Cursor_Backup CURSOR READ_ONLY FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('master','model','msdb','tempdb')  -- exclude these databases
 
OPEN Cursor_Backup   
FETCH NEXT FROM Cursor_Backup INTO @Base_Datos   
 
WHILE @@FETCH_STATUS = 0   
BEGIN   
   SET @Nombre_A = @Ruta_Archivos + @Base_Datos +  @Nombre_B   
   BACKUP DATABASE @Base_Datos TO DISK = @Nombre_A  
 
   FETCH NEXT FROM Cursor_Backup INTO @Base_Datos   
END   

 
CLOSE Cursor_Backup   
DEALLOCATE Cursor_Backup

Resultado de correr el script

realizar backup con tsqlQue sigue…

Se puede optimizar el script para agregar nuevas opciones de backups, como así también programar el mismo.

Crear indices faltantes

Como buscar y crear índices faltantes en nuestra base de datos

Navegando por la web me tope con esta conjunto de scripts recomendado por Microsoft que aseguran ser útil para cualquier DBA

https://gallery.technet.microsoft.com/Some-random-collection-of-b607bf1b

Como siempre son para MS SQL Server.

Entre ellos encontré uno muy útil que analiza las estadísticas de una base en producción y trate de generarte el TSQL para crear los índices recomendados faltantes

Veamos el código

/**********************************************
--Missing Index Script
**********************************************/

SELECT TOP 25
dm_mid.database_id AS DatabaseID,
dm_migs.avg_user_impact*(dm_migs.user_seeks+dm_migs.user_scans) Avg_Estimated_Impact,
dm_migs.last_user_seek AS Last_User_Seek,
OBJECT_NAME(dm_mid.OBJECT_ID,dm_mid.database_id) AS [TableName],
'CREATE INDEX [IX_' + OBJECT_NAME(dm_mid.OBJECT_ID,dm_mid.database_id) + '_'
+ REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.equality_columns,''),', ','_'),'[',''),']','') +
CASE
WHEN dm_mid.equality_columns IS NOT NULL AND dm_mid.inequality_columns IS NOT NULL THEN '_'
ELSE ''
END
+ REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.inequality_columns,''),', ','_'),'[',''),']','')
+ ']'
+ ' ON ' + dm_mid.statement
+ ' (' + ISNULL (dm_mid.equality_columns,'')
+ CASE WHEN dm_mid.equality_columns IS NOT NULL AND dm_mid.inequality_columns IS NOT NULL THEN ',' ELSE
'' END
+ ISNULL (dm_mid.inequality_columns, '')
+ ')'
+ ISNULL (' INCLUDE (' + dm_mid.included_columns + ')', '') AS Create_Statement
FROM sys.dm_db_missing_index_groups dm_mig
INNER JOIN sys.dm_db_missing_index_group_stats dm_migs
ON dm_migs.group_handle = dm_mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details dm_mid
ON dm_mig.index_handle = dm_mid.index_handle
WHERE dm_mid.database_ID = DB_ID()
ORDER BY Avg_Estimated_Impact DESC
GO

Resultado de correr el script

Luego de unos segundos veremos algo de este estilo:

buscando indices faltantes con tsqlPodremos ver el tiempo promedio estimado de mejora al realizar el índice, como el TSQL para crearlo.

(*) Un error que tiene el script es el nombre del índice que genera, que no debe superar los 128 caracteres, y en el mismo no lo contempla.

Por lo demás promete cumplir lo que ofrece….

Actualmente lo estoy probando en mis bases de producción como alternativa a la herramienta de análisis de rendimiento de MS SQL Server

Obtener el ultimo día del mes con SQL Server

Como obtener el último día del mes con TSQL en SQL Server

Anteriormente habíamos visto como podíamos obtener:

Primer y último día de Mes Anterior, Actual y Siguiente.

Si te interesa ( y trabajas con una versión anterior a MS SQL Server 2012), les dejo el tutorial anterior:

https://maurobernal.com.ar/blog/t-sql/primer-y-ultimo-dia-del-mes-con-sql-server-y-otros/

Pero en esta oportunidad veremos otra variante para obtener el último día del mes: actual, mes anterior y mes siguiente.

Usando la funtión EOMONTH()

A partir de Microsoft SQL Server 2012 se agregó la función EOMONTH()

https://docs.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql

La misma permite obtener el último día del mes

Veamos un ejemplo:

--GetDate() -> 14 Nov 2017

--Último día del mes Actual
select EOMONTH(getdate()) as UltDiaMesActual

--Último día del mes Anterior
select EOMONTH(getdate(),-1) as UltDiaMesAnterior

--Último día del mes Próximo
select EOMONTH(getdate(),1) as UltDiaMesProximo

Esto nos dará como resultado:

usando_eomonth_ejemploCon un poco de ingenio podemos obtener un poco más

A partir del código anterior, con un poco de ingenio, y con ayuda de la función DateAdd()

https://docs.microsoft.com/en-us/sql/t-sql/functions/dateadd-transact-sql

Si le agregamos un día podemos obtener el primer día del mes anterior, mes actual y mes próximo

--GetDate() -> 14 Nov 2017

--Primer día del Mes Anterior
select dateadd(d,1,EOMONTH(getdate(),-2)) as PrimerDiaMesAnterior

--Primer día del Mes Actual
select dateadd(d,1,EOMONTH(getdate(),-1)) as PrimerDiaMesActual

--Primer Dia del Mes Siguiente
select dateadd(d,1,EOMONTH(getdate())) as PrimerDiaMesSiguiente

El resultado sería el siguiente:

eomoth para primer dia del mes

 

No se olviden de comentar si les sirvió, !!! Y cualquier cosa que necesiten hacer es posible con un poco de paciencia…

Tutorial Rank y Dense_Rank

Aprende a usar Rank() y Dense_Rank()

Vamos primero con la documentación de estas dos funciones:

Rank:

https://docs.microsoft.com/en-us/sql/t-sql/functions/rank-transact-sql

Dense_Rank

https://docs.microsoft.com/en-us/sql/t-sql/functions/dense-rank-transact-sql

 

Entendiendo con un ejemplo

Primero crearemos un pequeña base de datos, que incluye un listado de vendedores, con sus ventas

IF EXISTS(SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('myTable'))
BEGIN;
    DROP TABLE [myTable];
END;
GO

CREATE TABLE [myTable] (
    [myTableID] INTEGER NOT NULL IDENTITY(1, 1),
    [Vendedor] VARCHAR(255) NULL,
    [Ventas] VARCHAR(100) NULL,
    PRIMARY KEY ([myTableID])
);
GO

INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Bowen','$1.60'),('Becker','$31.71'),('Stanton','$95.81'),('Weaver','$60.26'),('Park','$65.37'),('Cook','$80.55'),('Pruitt','$60.42'),('Roberson','$20.23'),('Gilbert','$81.98'),('Emerson','$44.32');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Harper','$1.60'),('Patrick','$98.08'),('Andrews','$35.71'),('Steele','$92.19'),('Moody','$1.90'),('Strong','$68.97'),('Rowland','$23.67'),('Barron','$79.18'),('Schultz','$80.94'),('Andrews','$1.92');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Cleveland','$58.03'),('Head','$46.60'),('Hickman','$25.67'),('Cooke','$7.19'),('Farrell','$25.46'),('Sutton','$29.80'),('Dominguez','$85.95'),('Meadows','$70.26'),('Horne','$32.67'),('Cantu','$49.44');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Mosley','$95.29'),('Gomez','$8.53'),('Noble','$81.25'),('Shaw','$47.67'),('Harper','$23.01'),('Reese','$2.46'),('Brown','$36.73'),('Hardin','$0.65'),('Marshall','$7.98'),('Combs','$60.59');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Hicks','$2.78'),('Cote','$15.58'),('Knight','$91.91'),('Gilliam','$75.10'),('Leblanc','$11.16'),('Franklin','$13.92'),('Powers','$1.45'),('Clark','$36.26'),('Rose','$22.70'),('Hoover','$78.61');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Hines','$45.97'),('Lowery','$29.76'),('Le','$63.35'),('Allison','$96.55'),('Fulton','$34.28'),('Cleveland','$46.02'),('Brewer','$1.60'),('Howe','$1.60'),('Sims','$26.47'),('Fox','$55.71');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Bentley','$28.30'),('Hahn','$81.10'),('Colon','$62.66'),('Le','$3.42'),('House','$90.24'),('Kemp','$93.13'),('Cooper','$85.59'),('Mosley','$46.40'),('Jacobs','$1.58'),('Dickson','$76.56');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Jacobs','$46.47'),('Moon','$77.90'),('Palmer','$52.45'),('Bray','$99.29'),('Franco','$50.64'),('Erickson','$21.77'),('Joyce','$32.19'),('Kline','$4.15'),('Barrera','$71.70'),('Jacobs','$58.56');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Mercer','$95.18'),('Horn','$43.12'),('Mendoza','$42.59'),('Mays','$59.19'),('Shaw','$33.63'),('Sawyer','$58.80'),('Chen','$43.88'),('Dorsey','$32.79'),('Howard','$50.02'),('Marshall','$81.84');
INSERT INTO myTable([Vendedor],[Ventas]) VALUES('Casey','$2.67'),('Boyer','$39.07'),('Richards','$31.92'),('Larson','$64.99'),('Drake','$42.46'),('Holmes','$28.37'),('Hicks','$21.46'),('Richardson','$89.33'),('Evans','$8.90'),('Crawford','$11.28');

 

Contenido de esta tabla

Esta tabla desordenada contiene el listado de vendedores, con sus respectivas Ventas

select * from myTable

Base para ejemplo de Dense Rank

Uso de Rank y Dense_Rank para armar ranking

La idea de estas dos funciones es armar un ranking.

Semejanza: Ambas, en el caso de que empaten le ponen el mismo número de ranking

Diferencia: Al caso siguiente luego del empate Rank no le pone el inmediato superior, si no que mantiene la cuenta de la cantidad de elementos que lleva hasta el momento y le pone el siguiente. A diferencia de Dense_Rank que continúa con el siguiente correlativo al del empate

 

Con Rank

select *, RANK() over (Order by Ventas) as Ranking from myTable

Uso de Rank

Con Dense_Rank

select *, DENSE_RANK() over ( Order by Ventas) as Ranking from myTable

Uso de dense_rankts