Compare commits

..
16 Commits
Author SHA1 Message Date
smishchuk 7ac2c85238 064 interface improvements 2026-07-28 14:28:27 +03:00
smishchuk d9de157635 064 queries optimized 2026-07-28 13:14:02 +03:00
smishchuk 164771bf78 063 cache bug fix 2026-07-28 10:59:21 +03:00
smishchuk 86500c8630 062 ­ excel fix 2026-07-27 10:42:56 +03:00
smishchuk b7d030567f 061 cfflush fix for file export 2026-07-27 10:36:31 +03:00
smishchuk 132acd7287 060 cyrillic fix 2026-07-26 23:33:20 +03:00
smishchuk 274643ed28 059 inmem full join with spec 2026-07-26 23:01:27 +03:00
smishchuk 59bf109ba5 058 manager 2026-07-22 13:27:09 +03:00
smishchuk 228023ba49 057 orrganization_status 2026-07-02 19:34:41 +03:00
smishchuk 6c952ca443 056 bugfix vms_on 2026-07-01 20:59:45 +03:00
smishchuk 8c5ddd2ae4 055 vm storage comments 2026-07-01 18:01:20 +03:00
smishchuk b7bc2388be 055 vm storage 2026-07-01 17:56:25 +03:00
smishchuk 07c09ba782 054 vsan free 2026-07-01 17:13:43 +03:00
smishchuk a2625d125f 054 minor fix 2026-06-30 21:26:01 +03:00
smishchuk 02e5a63572 052 capacity section 2026-06-30 17:41:10 +03:00
smishchuk 0b33a5a29e 052 capacity section 2026-06-30 17:40:26 +03:00
11 changed files with 670 additions and 279 deletions
+18 -9
View File
@@ -6,7 +6,7 @@
<!--- Set up the application. --->
<cfset this.Name = "PAYG" />
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 3, 0 ) />
<cfset this.applicationTimeout = createTimeSpan( 0, 1, 0, 0 ) />
<cfset this.sessionmanagement="Yes"/>
<cfset this.clientmanagement="No"/>
<cfset this.sessiontimeout=CreateTimeSpan(0, 0, 120, 0)/>
@@ -14,7 +14,7 @@
<cfset this.mappings = structNew() />
<cfset this.mappings["/mod"] = getDirectoryFromPath(getCurrentTemplatePath()) & "mod/" />
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath())&'mod')/>
<cfset this.datasource = "dwh"/>
<cfset this.datasource = "dwh"/>
<cfset this.defaultdatasource = this.datasource/>
<cfset request.DS = "#this.datasource#">
@@ -25,10 +25,23 @@
<!--- но датасорцы таинственно прочухались с прошлым пушем, без переноса инициализации в псевдоконструктор --->
<!--- а потом опять... --->
<cfset this.datasources["inmem"] = {
class: "org.hsqldb.jdbcDriver",
// Внимание наjdbc:hsqldb:mem:
connectionString: "jdbc:hsqldb:mem:lucee_mem;shutdown=false",
username: "sa",
password: "",
// Защита от "висяка" и исчезновения базы:
// заставляем Lucee держать минимум 1 коннект открытым всегда
connectionLimit: 5,
connectionMin: 1
}
/><!--- inmemory DB --->
<cfset COOKIEENCKEY = "PREVED!Y2"/>
<!--- Define the page request properties. --->
<cfsetting
requesttimeout="20"
requesttimeout="45"
showdebugoutput="false"
enablecfoutputonly="false"
/>
@@ -66,8 +79,6 @@
The API token is available in your personal configuration page. Click your name on the top right corner on every page, then click "Configure" to see your API token. (The URL $root/me/configure is a good shortcut.) You can also change your API token from here.
--->
<cfset request.UNDEFINED_USR_ID=-1/>
<!--- request.ROOT_USR_ID=1 not used --->
<cfset request.ANONYMOUS_USR_ID=2/>
@@ -75,8 +86,8 @@
<!--- global settings --->
<cfset request.RECORDS_PER_PAGE=500/>s
<cfset request.APP_VERSION="0.00.052"/>
<cfset request.RECORDS_PER_PAGE=500/>
<cfset request.APP_VERSION="0.00.065"/>
<cfset request.STAND=getStand()/>
<cflock scope="application" type="readonly" timeout=3>
@@ -260,8 +271,6 @@
</cfif>
</cfif>
<cfreturn />
</cffunction>
+98
View File
@@ -0,0 +1,98 @@
component {
/**
* HSQL 1.8
* Принимает Lucee Query, создает в HSQL временную таблицу и льет в нее данные
* @name Имя таблицы, которое ты хочешь использовать в SQL
* @data Сам запрос (результат queryExecute или cfhttp)
* @dsn Имя datasource для HSQL (по умолчанию "inmem")
*/
public string function register(required string name, required query data, string dsn = "inmem") {
var cols = arguments.data.columnList;
var meta = getMetaData(arguments.data);
//writedump(meta);
var colDefs = [];
var colTypes = {};
var params = [];
// 1. Генерируем "CREATE TEMP TABLE name (col1 TYPE, col2 TYPE...)"
for (var i = 1; i <= arrayLen(meta); i++) {
var colName = meta[i].name;
// Маппинг типов Lucee -> типы H2
var dbType = mapType(meta[i].typeName);
arrayAppend(colDefs, "#colName# #dbType#");
colTypes[colName] = meta[i].typeName;
}
//writedump(colDefs);
//var checkSql = "SELECT * FROM INFORMATION_SCHEMA.SYSTEM_TABLES WHERE TABLE_NAME = '#ucase(arguments.name)#';"
//var res = queryExecute(checkSql, {}, { datasource: arguments.dsn });
//if (res.recordCount EQ 0) {
var createSql = "DROP TABLE IF EXISTS #arguments.name#;
CREATE TEMPORARY TABLE #arguments.name#(#arrayToList(colDefs, ', ')#) ON COMMIT PRESERVE ROWS";
queryExecute(createSql, {}, { datasource: arguments.dsn });
//}
// 2. Цикл вставки
var insertSql = "INSERT INTO #arguments.name# (#cols#) VALUES (#repeatString("?,", listLen(cols)-1)#?)";
for (var row in arguments.data) {
var rowData = [];
for (var col in cols) {
arrayAppend(rowData, formatValue(row[col], colTypes[col]));
}
queryExecute(insertSql, rowData, { datasource: arguments.dsn });
}
return arguments.name;
}
/**
* Удалить временные таблицы (опционально, база сама почистит при закрытии коннекта)
*/
public void function drop(required string names, string dsn = "inmem") {
var list = arguments.names;
if (!isArray(list)) list = [list];
for (var name in list) {
queryExecute("DROP TABLE IF EXISTS #name#", {}, { datasource: arguments.dsn });
}
}
// --- Вспомогательная функция маппинга типов ---
private string function mapType(required string luceeType) {
switch (arguments.luceeType) {
case "VARCHAR": case "CHAR": case "LONGVARCHAR": return "LONGVARCHAR";
case "INTEGER": case "BIGINT": case "SMALLINT": case "TINYINT": return "INT";
case "DOUBLE": case "FLOAT": case "REAL": return "DOUBLE";
case "BOOLEAN": case "BIT": return "BIT";
case "DECIMAL": case "NUMERIC": return "DECIMAL(20,6)";
default: return "LONGVARCHAR"; // И тут тоже
}
}
private function formatValue(required any val, required string targetType) {
var isTextType = listFindNoCase("VARCHAR,CHAR,LONGVARCHAR", arguments.targetType);
// 1. Обработка пустых значений
if (isNull(arguments.val) || (isSimpleValue(arguments.val) && len(trim(arguments.val)) == 0)) {
// Если это текстовое поле — сохраняем пустую строку как есть
if (isTextType) {
return "";
}
// Для чисел, дат и булев — отдаем настоящий SQL NULL
return javaCast("null", "");
}
// 2. Форматирование непустых дат
if (listFindNoCase("DATE,TIMESTAMP,TIME", arguments.targetType)) {
return dateFormat(arguments.val, "yyyy-mm-dd") & " " & timeFormat(arguments.val, "HH:mm:ss");
}
// 3. Числа и непустой текст отдаем как есть
return arguments.val;
}
}
+270 -95
View File
@@ -55,7 +55,7 @@
</cftry>
</cffunction>
<m:prepare_ls entity="crm2cloud" settingsKey="crm2cloud" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
<m:prepare_ls entity="cloud_capacity" settingsKey="cloud_capacity" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
<cfquery name="qTS">
select
@@ -81,45 +81,58 @@ from (
group by "Cluster"), --->
usage as (
select "Cluster" as cluster
,count("UUID_VM") as vms
,sum("VM_vCPU_count") as vm_cores
,sum("VM_vCPU_count"*"VDC_CPU_Speed") as vm_ghz
,sum("VM_CPU_Reserv_GHz") as vm_ghz_reserved
,sum("VM_vCPU_count"*"VDC_CPU_Speed"*"VM_CPU_Reserv_perc"/100) as vm_ghz_reserved_c
,sum("VM_vCPU_count"*"VDC_CPU_Speed"*(case when "VM_CPU_Reserv_perc" IS null then 20 when "VM_CPU_Reserv_perc"<=20 then 20 else "VM_CPU_Reserv_perc" end)/100) as vm_ghz_promised
-- promised - зарезервированные ГГц, если включить минимальное согласованное резервирование
,sum("VM_RAM_Allocated"*"VM_is_ON") as vm_ram_alloc_on
,sum("VM_RAM_Allocated") as vm_ram_alloc
,sum("VM_RAM_Used") as vm_ram_used
,sum("VM_CPU_Used_AVG") as vm_ghz_usage
,sum("VM_is_ON") as vms_on
from vmreports.compute
where ts=(select max(ts) from vmreports.compute)
group by "Cluster"),
select
c."Cluster" as cluster
,count(c."UUID_VM") as vms
,sum(c."VM_vCPU_count") as vm_cores
,sum(c."VM_vCPU_count"*c."VM_is_ON") as vm_cores_on
,sum(c."VM_vCPU_count"*c."VDC_CPU_Speed") as vm_ghz
,sum(c."VM_vCPU_count"*c."VDC_CPU_Speed"*c."VM_is_ON") as vm_ghz_on
,sum(c."VM_CPU_Reserv_GHz") as vm_ghz_reserved
,sum(c."VM_vCPU_count"*c."VDC_CPU_Speed"*c."VM_CPU_Reserv_perc"/100) as vm_ghz_reserved_c
,sum(c."VM_vCPU_count"*c."VDC_CPU_Speed"*(case when c."VM_CPU_Reserv_perc" IS null then 20 when c."VM_CPU_Reserv_perc"<=20 then 20 else c."VM_CPU_Reserv_perc" end)/100) as vm_ghz_promised
-- promised - зарезервированные ГГц, если включить минимальное согласованное резервирование
,sum(c."VM_RAM_Allocated"*c."VM_is_ON") as vm_ram_alloc_on
,sum(c."VM_RAM_Allocated") as vm_ram_alloc
,sum(c."VM_RAM_Used") as vm_ram_used
,sum(c."VM_CPU_Used_AVG") as vm_ghz_usage
,sum(c."VM_is_ON") as vms_on
,sum(s."Disk_Allocated") as disk_allocated
,sum(s."Disk_Used") as disk_used
,sum(CASE WHEN c."Organization_Status"='prod' THEN c."VM_CPU_Used_AVG" ELSE 0 END ) as ghz_used_prod
,sum(CASE WHEN c."Organization_Status"='prod' THEN c."VM_RAM_Used" ELSE 0 END ) as ram_used_prod
,sum(CASE WHEN c."Organization_Status"='prod' THEN s."Disk_Used" ELSE 0 END ) as disk_used_prod
from vmreports.compute c
left outer join vmreports.storage s on(c."UUID_VM"=s."VM_UUID")
where c.ts=(select max(ts) from vmreports.compute)
AND s.ts=(select max(ts) from vmreports.storage)
group by c."Cluster"),
cluster_stat as (
SELECT
h."Cluster" as cluster
,h."Cluster_v2" as cluster_v2
,m.models
,COUNT(*) as hosts_total
,COUNT(*)-1 as hosts_ha /*не вполне корректно, хосты разного размера, отказ по-разному влияет*/
,sum(CASE WHEN "Maintenance"='inMaintenance' THEN 1 ELSE 0 END) as hosts_in_maintenance
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN 1 ELSE 0 END) as hosts_in_service
,sum("CPU_Cores") as cores
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Cores" ELSE 0 END) as cores_in_service
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Cores"*"CPU_Speed" ELSE 0 END) as ghz_in_service
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPUtoVM" ELSE 0 END) as ghz_provisioned
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "RAMtoVM" ELSE 0 END) as gb_provisioned
--,sum("CPU_Used_AVG") as host_ghz_usage
--,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Used_AVG" ELSE 0 END) as host_ghz_usage
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Used" ELSE 0 END) as host_ghz_usage
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "RAM_Total" ELSE 0 END) as ram_in_service
,avg(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Speed" ELSE 0 END) as ghz
,max("CPUtoVM") as ghz_subtract_ha
,max("RAMtoVM") as gb_subtract_ha
,CASE WHEN sum("CPU_Cores"*"CPU_Speed") > 0 THEN sum("CPU_Used_AVG")/sum("CPU_Cores"*"CPU_Speed")*100 ELSE NULL END as cpu_usage_perc
h."Cluster" as cluster
,h."Cluster_v2" as cluster_v2
,m.models
,COUNT(*) as hosts_total
,COUNT(*)-1 as hosts_ha /*не вполне корректно, хосты разного размера, отказ по-разному влияет*/
,sum(CASE WHEN "Maintenance"='inMaintenance' THEN 1 ELSE 0 END) as hosts_in_maintenance
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN 1 ELSE 0 END) as hosts_in_service
,sum("CPU_Cores") as cores
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Cores" ELSE 0 END) as cores_in_service
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Cores"*"CPU_Speed" ELSE 0 END) as ghz_in_service
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPUtoVM" ELSE 0 END) as ghz_provisioned
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "RAMtoVM" ELSE 0 END) as gb_provisioned
--,sum("CPU_Used_AVG") as host_ghz_usage
--,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Used_AVG" ELSE 0 END) as host_ghz_usage
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Used" ELSE 0 END) as host_ghz_usage
,sum(CASE WHEN "Maintenance"='notInMaintenance' THEN "RAM_Total" ELSE 0 END) as ram_in_service
,avg(CASE WHEN "Maintenance"='notInMaintenance' THEN "CPU_Speed" ELSE 0 END) as ghz
,max("CPUtoVM") as ghz_subtract_ha
,max("RAMtoVM") as gb_subtract_ha
,sum("RAM_Total")/sum("CPU_Cores") as gb_per_core
,CASE WHEN sum("CPU_Cores"*"CPU_Speed") > 0 THEN sum("CPU_Used_AVG")/sum("CPU_Cores"*"CPU_Speed")*100 ELSE NULL END as cpu_usage_perc
FROM vmreports.host h
LEFT OUTER JOIN (
SELECT hi."Cluster", STRING_AGG(DISTINCT hi."Model" || ' [' || (hi.cnt::text) || '] ',', ') as models
@@ -142,8 +155,13 @@ cluster_naming (cluster,commercial_name) AS (VALUES
,('cl05-1c','msk1, AMD Raphael 4,5 ГГц')
,('cl06-vsan','msk1, Intel Ice Lake 2,8 ГГц')
,('cl07-vsan','msk1, AMD Genoa 4,0 ГГц')
)
),
vsan as (
SELECT "ClusterNew" as cluster_v2, "Total" as total, "Usable" as usable, "Used" as used, "EffectiveFree" as effective_free
FROM vmreports.vsan_storage
WHERE ts=(SELECT max(ts) FROM vmreports.vsan_storage)
)
select
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
@@ -151,40 +169,56 @@ select
<d:field title="cluster v2">h.cluster_v2</d:field>
<d:field title="Коммерческое название">n.commercial_name</d:field>
<d:field title="Models">h.models</d:field>
<d:field title="Hosts total">coalesce(h.hosts_total,0) as hosts_total</d:field>
<d:field title="Hosts HA">coalesce(h.hosts_ha,0) as hosts_ha</d:field>
<d:field title="Hosts in mainte nance">coalesce(h.hosts_in_maintenance,0) as hosts_in_maintenance</d:field>
<d:field title="Hosts in service">coalesce(h.hosts_in_service,0) as hosts_in_service</d:field>
<d:field title="Cores Total">coalesce(h.cores,0) as cores</d:field>
<d:field title="Cores in service">coalesce(h.cores_in_service,0) as cores_in_service</d:field>
<d:field title="GHz in service">coalesce(h.ghz_in_service,0) as ghz_in_service</d:field>
<d:field title="Host GHz used">coalesce(h.host_ghz_usage,0) as host_ghz_usage</d:field>
<d:field title="Payload GHz used">coalesce(u.vm_ghz_usage,0) as vm_ghz_usage</d:field>
<d:field title="CPU GHz">coalesce(h.ghz,0) as ghz</d:field>
<d:field title="RAM GB in service">coalesce(h.ram_in_service,0) as ram_in_service</d:field>
<d:field title="Host CPU usage %">coalesce(h.cpu_usage_perc,0) as cpu_usage_perc</d:field>
<d:field title="Hosts total" cfSqlType="CF_SQL_INTEGER">coalesce(h.hosts_total,0) as hosts_total</d:field>
<d:field title="Hosts HA" cfSqlType="CF_SQL_INTEGER">coalesce(h.hosts_ha,0) as hosts_ha</d:field>
<d:field title="Hosts in mainte nance" cfSqlType="CF_SQL_INTEGER">coalesce(h.hosts_in_maintenance,0) as hosts_in_maintenance</d:field>
<d:field title="Hosts in service" cfSqlType="CF_SQL_INTEGER">coalesce(h.hosts_in_service,0) as hosts_in_service</d:field>
<d:field title="Cores Total" cfSqlType="CF_SQL_INTEGER">coalesce(h.cores,0) as cores</d:field>
<d:field title="Cores in service" cfSqlType="CF_SQL_INTEGER">coalesce(h.cores_in_service,0) as cores_in_service</d:field>
<d:field title="GHz in service" cfSqlType="CF_SQL_NUMERIC">coalesce(h.ghz_in_service,0) as ghz_in_service</d:field>
<d:field title="Host GHz used" cfSqlType="CF_SQL_NUMERIC">coalesce(h.host_ghz_usage,0) as host_ghz_usage</d:field>
<d:field title="Payload GHz used" cfSqlType="CF_SQL_NUMERIC">coalesce(u.vm_ghz_usage,0) as vm_ghz_usage</d:field>
<d:field title="CPU freq GHz" cfSqlType="CF_SQL_NUMERIC">coalesce(h.ghz,0) as ghz</d:field>
<d:field title="RAM GB in service" cfSqlType="CF_SQL_NUMERIC">coalesce(h.ram_in_service,0) as ram_in_service</d:field>
<d:field title="Host CPU usage %" cfSqlType="CF_SQL_NUMERIC">coalesce(h.cpu_usage_perc,0) as cpu_usage_perc</d:field>
<!--- <d:field title="Hosts in use">h.hosts</d:field> --->
<d:field title="Cores Total">coalesce(h.cores,0) as cores_total</d:field>
<d:field title="Cores Total" cfSqlType="CF_SQL_INTEGER">coalesce(h.cores,0) as cores_total</d:field>
<!--- <d:field title="GHz Capacity">c.ghz as GHz_Capacity</d:field> --->
<d:field title="GHz Provisioned">coalesce(h.ghz_provisioned - CASE WHEN hosts_in_maintenance > 0 THEN 0 ELSE h.ghz_subtract_ha END,0) as GHz_Provisioned</d:field><!--- за вычетом согласованных резервов на хосте и на HA --->
<d:field title="GB Provisioned">coalesce(h.gb_provisioned - CASE WHEN hosts_in_maintenance > 0 THEN 0 ELSE h.gb_subtract_ha END,0) as GB_Provisioned</d:field><!--- за вычетом согласованных резервов на хосте и на HA --->
<d:field title="Payload GHz reserved">coalesce(u.vm_ghz_reserved,0) as vm_ghz_reserved</d:field>
<d:field title="GHz обещанные">coalesce(u.vm_ghz_promised,0) as vm_ghz_promised</d:field>
<d:field title="CPU GHz provision rate %">coalesce(round((u.vm_ghz_promised/h.ghz_provisioned)::numeric,2)*100,0) as GHz_provision_rate</d:field>
<d:field title="Payload RAM GB alloc">coalesce(u.vm_ram_alloc,0) as vm_ram_alloc</d:field>
<d:field title="Payload RAM GB alloc ВКЛ">coalesce(u.vm_ram_alloc_on,0) as vm_ram_alloc_on</d:field>
<d:field title="Payload RAM GB used">coalesce(u.vm_ram_used,0) as vm_ram_used</d:field>
<d:field title="RAM alloc %">coalesce(round((u.vm_ram_alloc/h.gb_provisioned)::numeric,2)*100,0) as GB_alloc_perc</d:field>
<d:field title="RAM usage %">coalesce(round((u.vm_ram_used/h.gb_provisioned)::numeric,2)*100,0) as GB_usage_perc</d:field>
<d:field title="Пере подписка vCPU">coalesce(round((u.vm_cores/h.cores)::numeric,1),0) as oversubscription</d:field>
<d:field title="Payload cores">coalesce(u.vm_cores,0) as vm_cores</d:field>
<d:field title="VMs">coalesce(u.vms,0) as vms</d:field>
<d:field title="VMs ON">coalesce(u.vms_on,0) as vms_on</d:field>
<d:field title="Payload CPU Usage %">coalesce(u.vm_ghz_usage/h.ghz_in_service*100,0) as vm_cpu_usage_perc</d:field>
<d:field title="GHz Provisioned" cfSqlType="CF_SQL_NUMERIC">coalesce(h.ghz_provisioned - CASE WHEN hosts_in_maintenance > 0 THEN 0 ELSE h.ghz_subtract_ha END,0) as GHz_Provisioned</d:field><!--- за вычетом согласованных резервов на хосте и на HA --->
<d:field title="GB Provisioned" cfSqlType="CF_SQL_NUMERIC">coalesce(h.gb_provisioned - CASE WHEN hosts_in_maintenance > 0 THEN 0 ELSE h.gb_subtract_ha END,0) as GB_Provisioned</d:field><!--- за вычетом согласованных резервов на хосте и на HA --->
<d:field title="Payload GHz reserved" cfSqlType="CF_SQL_NUMERIC">coalesce(u.vm_ghz_reserved,0) as vm_ghz_reserved</d:field>
<d:field title="GHz обещанные" cfSqlType="CF_SQL_NUMERIC">coalesce(u.vm_ghz_promised,0) as vm_ghz_promised</d:field>
<d:field title="CPU GHz provision rate %" cfSqlType="CF_SQL_NUMERIC">coalesce(round((u.vm_ghz_promised/h.ghz_provisioned)::numeric,2)*100,0) as GHz_provision_rate</d:field>
<d:field title="Payload RAM GB alloc" cfSqlType="CF_SQL_NUMERIC">coalesce(u.vm_ram_alloc,0) as vm_ram_alloc</d:field>
<d:field title="Payload RAM GB alloc ВКЛ" cfSqlType="CF_SQL_NUMERIC">coalesce(u.vm_ram_alloc_on,0) as vm_ram_alloc_on</d:field>
<d:field title="Payload RAM GB used" cfSqlType="CF_SQL_NUMERIC">coalesce(u.vm_ram_used,0) as vm_ram_used</d:field>
<d:field title="RAM alloc %" cfSqlType="CF_SQL_NUMERIC">coalesce(round((u.vm_ram_alloc/h.gb_provisioned)::numeric,2)*100,0) as GB_alloc_perc</d:field>
<d:field title="RAM usage %" cfSqlType="CF_SQL_NUMERIC">coalesce(round((u.vm_ram_used/h.gb_provisioned)::numeric,2)*100,0) as GB_usage_perc</d:field>
<d:field title="Пере подписка vCPU" cfSqlType="CF_SQL_NUMERIC">coalesce(round((u.vm_cores/h.cores)::numeric,1),0) as oversubscription</d:field><!--- не только по включенным --->
<d:field title="Payload cores" cfSqlType="CF_SQL_INTEGER">coalesce(u.vm_cores,0) as vm_cores</d:field>
<d:field title="Payload cores ВКЛ" cfSqlType="CF_SQL_INTEGER">coalesce(u.vm_cores_on,0) as vm_cores_on</d:field>
<d:field title="VMs" cfSqlType="CF_SQL_INTEGER">coalesce(u.vms,0) as vms</d:field>
<d:field title="VMs ВКЛ" cfSqlType="CF_SQL_INTEGER">coalesce(u.vms_on,0) as vms_on</d:field>
<d:field title="Payload CPU Usage %" cfSqlType="CF_SQL_NUMERIC">coalesce(u.vm_ghz_usage/h.ghz_in_service*100,0) as vm_cpu_usage_perc</d:field>
<d:field title="GB/pCore" cfSqlType="CF_SQL_NUMERIC">coalesce(h.gb_per_core,0) as gb_per_core</d:field>
<d:field title="vSAN Total" cfSqlType="CF_SQL_NUMERIC">coalesce(s.total,0) as total</d:field>
<d:field title="vSAN Usable" cfSqlType="CF_SQL_NUMERIC">coalesce(s.usable,0) as usable</d:field>
<d:field title="vSAN Used" cfSqlType="CF_SQL_NUMERIC">coalesce(s.used,0) as used</d:field>
<d:field title="vSAN Effective Free" cfSqlType="CF_SQL_NUMERIC">coalesce(s.effective_free,0) as effective_free</d:field>
<d:field title="Disk Allocated" cfSqlType="CF_SQL_NUMERIC">coalesce(u.disk_allocated,0) as disk_allocated</d:field>
<d:field title="Disk Used" cfSqlType="CF_SQL_NUMERIC">coalesce(u.disk_used,0) as disk_used</d:field>
<d:field title="GHz Used Prod" cfSqlType="CF_SQL_NUMERIC">coalesce(u.ghz_used_prod,0) as ghz_used_prod</d:field>
<d:field title="RAM Used Prod" cfSqlType="CF_SQL_NUMERIC">coalesce(u.ram_used_prod,0) as ram_used_prod</d:field>
<d:field title="Disk Used Prod" cfSqlType="CF_SQL_NUMERIC">coalesce(u.disk_used_prod,0) as disk_used_prod</d:field>
</d:field_set>
from cluster_stat h
left outer join usage u on (h.cluster=u.cluster)
left outer join cluster_naming n on (h.cluster=n.cluster)
left outer join vsan s on (h.cluster_v2=s.cluster_v2)
where 1=1 <!--- <m:filter_build filter=#pageInfo.settings.filter#/> --->
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/>
</cfquery>
@@ -203,13 +237,26 @@ select
,sum(gb_provisioned) as gb_provisioned
,sum(cores_in_service) as cores_in_service
,sum(vm_cores) as vm_cores
,sum(vm_cores_on) as vm_cores_on
,sum(vm_ghz_usage) as vm_ghz_usage
,sum(vm_ghz_reserved) as vm_ghz_reserved
,sum(vm_ghz_promised) as vm_ghz_promised
,sum(vm_ram_alloc) as vm_ram_alloc
,sum(vm_ram_alloc_on) as vm_ram_alloc_on
,sum(vm_ram_used) as vm_ram_used
,sum(vms) as vms
,sum(vms_on) as vms_on
,sum(cores*ghz)/sum(cores) as ghz <!--- рискованно все же делить --->
,sum(disk_allocated) as disk_allocated
,sum(disk_used) as disk_used
,sum(usable) as usable
,sum(ghz_used_prod) as ghz_used_prod
,sum(ram_used_prod) as ram_used_prod
,sum(disk_used_prod) as disk_used_prod
from qRead
</cfquery>
@@ -231,35 +278,38 @@ from qRead
<cfoutput query="qTS">
<h3 style="display:inline-block; margin-right:2em;">Актуальность данных</h3>
<b>VM:</b> #dateFormat(ts_compute,"YYYY-MM-DD")# #timeFormat(ts_compute,"HH:MM")#
<b>Хосты:</b> #dateFormat(ts_host,"YYYY-MM-DD")# #timeFormat(ts_host,"HH:MM")#
<b>VM:</b> <span <cfif dateDiff("h",ts_compute,Now()) GT 24> class="err"</cfif>>#dateFormat(ts_compute,"YYYY-MM-DD")# #timeFormat(ts_compute,"HH:MM")#</span>
<b>Хосты:</b> <span <cfif dateDiff("h",ts_host,Now()) GT 24> class="err"</cfif>>#dateFormat(ts_host,"YYYY-MM-DD")# #timeFormat(ts_host,"HH:MM")#</span>
</cfoutput>
<h3>Свободно</h3>
<table class="worktable">
<thead>
<tr>
<!--- <thead> --->
<layout:grid_head titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray#>
<!--- <tr> --->
<th width="5%" rowspan="2"><layout:column_head name="cluster_v1"/></th>
<th width="5%" rowspan="2"><layout:column_head name="cluster_v2"/></th>
<th width="10%" rowspan="2"><layout:column_head name="commercial_name"/></th>
<th width="3%" rowspan="2"><layout:column_head name="hosts_total"/></th>
<th colspan="6">Свободно</th>
<th colspan="7">Свободно</th>
<th width="3%" rowspan="2">ВМ размещено</th>
</layout:grid_head>
</tr>
<tr><th width="5%">RAM GB by alloc</th>
<th width="5%">RAM GB by usage</th>
<!--- </tr> --->
</layout:grid_head>
<tr>
<th width="5%">RAM GB by alloc</th>
<th width="5%">RAM GB by usage</th>
<th width="5%">CPU GHz (текущий резерв)</th>
<th width="5%">Ядра 20% (текущий резерв)</th>
<th width="5%">Ядра 50% (текущий резерв)</th>
<th width="5%">Ядра 80% (текущий резерв)</th>
<th width="5%">vSAN GB (alloc)</th>
</tr>
</thead>
<!--- </thead> --->
<!--- <tbody> --->
<cfoutput query="qRead">
<tr>
<td>#cluster_v1#</td>
@@ -278,6 +328,8 @@ from qRead
<td class="r<cfif safeCompareNum(ghz_provisioned - vm_ghz_reserved, "LE", 0)> err</cfif>" style="font-size:130%"><cfif ghz GT 0>#safeNumberFormat((ghz_provisioned-vm_ghz_reserved)/ghz/0.5,"0")#</cfif></td>
<td class="r<cfif safeCompareNum(ghz_provisioned - vm_ghz_reserved, "LE", 0)> err</cfif>" style="font-size:130%"><cfif ghz GT 0>#safeNumberFormat((ghz_provisioned-vm_ghz_reserved)/ghz/0.8,"0")#</cfif></td>
<td class="r" style="font-size:130%">#safeNumberFormat(effective_free,"0")#</td>
<!--- <td class="r<cfif safeCompareNum(ghz_provisioned - vm_ghz_promised, "LE", 0)> err</cfif>" style="font-size:130%">#safeNumberFormat(ghz_provisioned-vm_ghz_promised,".0")#</td>
<td class="r<cfif safeCompareNum(ghz_provisioned - vm_ghz_promised, "LE", 0)> err</cfif>" style="font-size:130%">#safeNumberFormat((ghz_provisioned-vm_ghz_promised)/ghz/0.2,"0")#</td>
<td class="r<cfif safeCompareNum(ghz_provisioned - vm_ghz_promised, "LE", 0)> err</cfif>" style="font-size:130%">#safeNumberFormat((ghz_provisioned-vm_ghz_promised)/ghz/0.5,"0")#</td>
@@ -286,6 +338,7 @@ from qRead
</tr>
</cfoutput>
<!--- </tbody> --->
</table>
<!--- <i>Жесткий резерв - если включим минимальное резервирование 20%</i><br/>
<i>Доступная память указана по выделенному объему (используется меньше, доступно больше)</i><br/> --->
@@ -367,9 +420,32 @@ from qRead
<td class="r">#numberFormat(GB_alloc_perc,"0")#</td>
<td class="r">#numberFormat(GB_usage_perc,"0")#</td>
<td class="r">#vms#</td>
<td class="r"><cftry>#numberFormat(vm_cores/vms,".0")#&nbsp;core #numberFormat(vm_ghz_usage/vms,".0")#&nbsp;GHz #numberFormat(vm_ghz_usage/vm_cores/ghz*100,"0")#% #numberFormat(vm_ram_alloc/vms,".0")#(#numberFormat(vm_ram_used/vms,".0")#)&nbsp;GB <cfcatch></cfcatch></cftry></td>
<td class="r"><!--- <cftry>
#numberFormat(vm_cores/vms,".0")#&nbsp;core
#numberFormat(vm_ghz_usage/vms_on,".0")#&nbsp;GHz
#numberFormat(vm_ghz_usage/vm_cores_on/ghz*100,"0")#%
#numberFormat(vm_ram_alloc/vms,".0")#(#numberFormat(vm_ram_used/vms_on,".0")#)&nbsp;GB
#numberFormat(disk_allocated/vms,".0")#(#numberFormat(disk_used/vms,".0")#)&nbsp;GB
<cfcatch><cfdump var=#cfcatch#></cfcatch></cftry></td> --->
<cftry>
<cfif vms NEQ 0>#numberFormat(vm_cores/vms,".0")#<cfelse> ? </cfif> &nbsp;core
<cfcatch type="any"></cfcatch></cftry>
<cftry>
<cfif vms_on NEQ 0>#numberFormat(vm_ghz_usage/vms_on,".0")#<cfelse> ? </cfif>&nbsp;GHz
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
<cftry>
<cfif vm_cores_on NEQ 0 AND ghz NEQ 0>#numberFormat(vm_ghz_usage/vm_cores_on/ghz*100,"0")#<cfelse> ? </cfif>%
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
<cftry>
<cfif vms NEQ 0>#numberFormat(vm_ram_alloc/vms,".0")#<cfelse> ? </cfif>(<cfif vms_on NEQ 0>#numberFormat(vm_ram_used/vms_on,".0")#<cfelse>?</cfif>)&nbsp;GB
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
<cftry>
<cfif vms NEQ 0>#numberFormat(disk_allocated/vms,".0")#(#numberFormat(disk_used/vms,".0")#)<cfelse> ? </cfif>&nbsp;GB
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
</td>
</tr>
</cfoutput>
<cfoutput query="qTotal">
<tr class="b">
<td colspan="4" class="r b"> Итого</td>
@@ -401,23 +477,32 @@ from qRead
<td class="r" style="font-size:130%;"><cfif ram_in_service NEQ 0>#numberFormat(vm_ram_used/ram_in_service*100,"0")#</cfif></td>
<td class="r">#vms#</td>
<td class="r">
<cftry>
<cfif vms NEQ 0>#numberFormat(vm_cores/vms,".0")#&nbsp;core</cfif>
<cfif vms NEQ 0>#numberFormat(vm_ghz_usage/vms,".0")#&nbsp;GHz</cfif>
<cfif vm_cores NEQ 0 AND ghz NEQ 0>#numberFormat(vm_ghz_usage/vm_cores/ghz*100,"0")#%</cfif> <!--- *** тут не уверен --->
<cfif vms NEQ 0>#numberFormat(vm_ram_alloc/vms,".0")#(#numberFormat(vm_ram_used/vms,".0")#)&nbsp;GB</cfif>
<cfcatch></cfcatch></cftry>
<cftry>
<cfif vms NEQ 0>#numberFormat(vm_cores/vms,".0")#<cfelse> ? </cfif> &nbsp;core
<cfcatch type="any"></cfcatch></cftry>
<cftry>
<cfif vms_on NEQ 0>#numberFormat(vm_ghz_usage/vms_on,".0")#<cfelse> ? </cfif>&nbsp;GHz
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
<cftry>
<cfif vm_cores_on NEQ 0 AND ghz NEQ 0>#numberFormat(vm_ghz_usage/vm_cores_on/ghz*100,"0")#<cfelse> ? </cfif>%
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
<cftry>
<cfif vms NEQ 0>#numberFormat(vm_ram_alloc/vms,".0")#<cfelse> ? </cfif>(<cfif vms_on NEQ 0>#numberFormat(vm_ram_used/vms_on,".0")#<cfelse>?</cfif>)&nbsp;GB
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
<cftry>
<cfif vms NEQ 0>#numberFormat(disk_allocated/vms,".0")#(#numberFormat(disk_used/vms,".0")#)<cfelse> ? </cfif>&nbsp;GB
<cfcatch type="any"><cfdump var=#cfcatch#></cfcatch></cftry>
</td>
</tr>
</cfoutput>
</table>
<!--- <cfdump var=#qCharge#/> --->
<!--- <cfdump var=#qTotal#/> --->
<i>Пока выводим избыточный набор колонок для контроля. Кроме того, еще не выбрали, какие колонки удобнее и релевантнее</i>
<br/>
<i>* CPU GHz provision rate % - отношение зарезервированной частоты (с учетом 20% резерва по умолчанию) к наличной частоте процессоров</i>
<i>* CPU GHz provision rate % - отношение зарезервированной частоты (с учетом 20% резерва по умолчанию) к наличной частоте процессоров (считая выключенные ВМ - поэтому "мертвые" ВМ искажают статистику, кроме того, что занимают диск)</i>
<br/>
<i>* Для средней ВМ указана аллоцированная память, а в скобках - используемая </i>
<i>* Для средней ВМ указана аллоцированная память, в скобках - используемая, далее аллоцированное дисковое пространство, в скобках используемое. Диск считается без разделения по политикам (2do). ГГц на ВМ, процент загрузки ядер (** проверить), используемая память - считается по включенным ВМ. Количество ядер, аллоцированная память и диск - по всем ВМ</i>
<br/>
<!--- <cfchart
format="png"
@@ -446,6 +531,12 @@ from qRead
<h3>Техническая утилизация</h3>
<layout:grid_summary
recordCount=#qRead.recordCount#
footerOut="gridFooter"
excelLink="Yes"
jsonLink="Yes"
/>
<table class="worktable">
<thead>
@@ -457,6 +548,7 @@ from qRead
<th width="3%"><layout:column_head name="hosts_total"/></th>
<th width="3%"><layout:column_head name="ghz"/></th>
<th width="3%"><layout:column_head name="gb_per_core"/></th>
<th width="3%"><layout:column_head name="vms"/></th>
<th width="3%"><layout:column_head name="vms_on"/></th>
@@ -465,24 +557,30 @@ from qRead
<th width="3%"><layout:column_head name="vm_cpu_usage_perc"/></th>
<th width="3%"><layout:column_head name="oversubscription"/></th>
<th width="3%"><layout:column_head name="cores_total"/></th>
<th width="3%"><layout:column_head name="cores_in_service"/></th>
<th width="3%"><layout:column_head name="ghz_in_service"/></th>
<th width="3%"><layout:column_head name="ghz_provisioned"/></th>
<th width="3%"><layout:column_head name="vm_ghz_reserved"/></th>
<th width="3%"><layout:column_head name="vm_ghz_usage"/></th>
<th width="3%"><layout:column_head name="vm_cores"/></th>
<th width="3%"><layout:column_head name="vm_cores_on"/></th>
<th width="3%"><layout:column_head name="gb_provisioned"/></th>
<th width="3%"><layout:column_head name="vm_ram_alloc"/></th>
<th width="3%"><layout:column_head name="vm_ram_alloc_on"/></th>
<th width="3%"><layout:column_head name="vm_ram_used"/></th>
<th width="3%"><layout:column_head name="GB_alloc_perc"/></th>
<th width="3%">RAM allloc вкл. ВМ %</th>
<th width="3%">RAM allloc %</th>
<th width="3%">RAM allloc ВКЛ %</th>
<th width="3%"><layout:column_head name="GB_usage_perc"/></th>
<th width="3%">Емкость vSAN GB</th>
<th width="3%">Свободно vSAN % alloc</th>
<th width="3%">Свободно vSAN % used</th>
<th width="3%"><layout:column_head name="ghz_used_prod"/></th>
<th width="3%"><layout:column_head name="ram_used_prod"/></th>
<th width="3%"><layout:column_head name="disk_used_prod"/></th>
</layout:grid_head>
</thead>
<cfoutput query="qRead">
@@ -493,6 +591,7 @@ from qRead
<td class="r">#hosts_total#</td>
<td class="r" style="font-size:120%">#numberFormat(ghz,".0")#</td>
<td class="r" style="font-size:120%">#numberFormat(gb_per_core,".0")#</td>
<td class="r" style="font-size:120%">#numberFormat(vms,"0")#</td>
<td class="r" style="font-size:120%">#numberFormat(vms_on,"0")#</td>
@@ -500,18 +599,94 @@ from qRead
<td class="c" style="font-size:130%;">#numberFormat(vm_cpu_usage_perc,"0")#</td>
<td class="r">#oversubscription#</td>
<td class="r">#cores_total#</td>
<td class="r">#cores_in_service#</td>
<td class="r">#safeNumberFormat(ghz_in_service,".0")#</td>
<td class="r">#numberFormat(ghz_provisioned,".0")#</td>
<td class="r">#numberFormat(vm_ghz_reserved,".0")#</td>
<td class="r">#numberFormat(vm_ghz_usage,".0")#</td>
<td class="r">#vm_cores#</td>
<td class="r">#vm_cores_on#</td>
<td class="r">#numberFormat(gb_provisioned,"0")#</td>
<td class="r">#numberFormat(vm_ram_alloc,"0")#</td>
<td class="r">#numberFormat(vm_ram_alloc_on,"0")#</td>
<td class="r">#numberFormat(vm_ram_used,"0")#</td>
<td class="c" style="font-size:130%;"><cfif ram_in_service NEQ 0>#numberFormat(vm_ram_alloc/ram_in_service*100,"0")#</cfif></td>
<td class="c" style="font-size:130%;"><cfif ram_in_service NEQ 0>#numberFormat(vm_ram_alloc_on/ram_in_service*100,"0")#</cfif></td>
<td class="c" style="font-size:130%;"><cfif ram_in_service NEQ 0>#numberFormat(vm_ram_used/ram_in_service*100,"0")#</cfif></td>
<!--- <td class="c" style="font-size:130%;"><cfif ram_in_service NEQ 0>#numberFormat(vm_ram_alloc/ram_in_service*100,"0")#</cfif></td> --->
<td class="c" style="font-size:130%;">#numberFormat(GB_alloc_perc,"0")#</td>
<td class="c" style="font-size:130%;"><cfif gb_provisioned NEQ 0>#numberFormat(vm_ram_alloc_on/gb_provisioned*100,"0")#</cfif></td>
<td class="c" style="font-size:130%;"><cfif gb_provisioned NEQ 0>#numberFormat(vm_ram_used/gb_provisioned*100,"0")#</cfif></td>
<td class="c" style="font-size:130%;">#safeNumberFormat(usable,"0")#</td>
<td class="c" style="font-size:130%;">
<cfif usable GT 0>
<cftry>
#numberFormat(effective_free/usable*100,"0")#
<cfcatch type="any"></cfcatch>
</cftry>
</cfif>
</td>
<td class="c" style="font-size:130%;">
<cfif usable GT 0>
<cftry>
#numberFormat((usable-used)/usable*100,"0")#
<cfcatch type="any"></cfcatch>
</cftry>
</cfif>
</td>
<td class="c">#safeNumberFormat(ghz_used_prod,".0")#</td>
<td class="c">#safeNumberFormat(ram_used_prod,"0")#</td>
<td class="c">#safeNumberFormat(disk_used_prod,"0")#</td>
</tr>
</cfoutput>
<cfoutput query="qTotal">
<tr class="b">
<td colspan="3" class="r b"> Итого</td>
<td class="r">#hosts_total#</td>
<td class="r" style="font-size:120%">#numberFormat(ghz,".0")#</td>
<td class="r" style="font-size:120%"></td>
<td class="r" style="font-size:120%">#numberFormat(vms,"0")#</td>
<td class="r" style="font-size:120%">#numberFormat(vms_on,"0")#</td>
<td class="c" style="font-size:130%;"></td>
<td class="c" style="font-size:130%;"></td>
<td class="r"></td>
<td class="r">#cores_total#</td>
<td class="r">#cores_in_service#</td>
<td class="r">#safeNumberFormat(ghz_in_service,".0")#</td>
<td class="r">#numberFormat(ghz_provisioned,".0")#</td>
<td class="r">#numberFormat(vm_ghz_reserved,".0")#</td>
<td class="r">#numberFormat(vm_ghz_usage,".0")#</td>
<td class="r">#vm_cores#</td>
<td class="r">#vm_cores_on#</td>
<td class="r">#numberFormat(gb_provisioned,"0")#</td>
<td class="r">#numberFormat(vm_ram_alloc,"0")#</td>
<td class="r">#numberFormat(vm_ram_alloc_on,"0")#</td>
<td class="r">#numberFormat(vm_ram_used,"0")#</td>
<td class="c" style="font-size:130%;"></td>
<td class="c" style="font-size:130%;"></td>
<td class="c" style="font-size:130%;"></td>
<td class="c" style="font-size:130%;">#safeNumberFormat(usable,"0")#</td>
<td class="c" style="font-size:130%;">
<cfif usable GT 0>
<cftry>
#numberFormat(effective_free/usable*100,"0")#
<cfcatch type="any"></cfcatch>
</cftry>
</cfif>
</td>
<td class="c" style="font-size:130%;">
<cfif usable GT 0>
<cftry>
#numberFormat((usable-used)/usable*100,"0")#
<cfcatch type="any"></cfcatch>
</cftry>
</cfif>
</td>
<td class="c">#safeNumberFormat(ghz_used_prod,".0")#</td>
<td class="c">#safeNumberFormat(ram_used_prod,"0")#</td>
<td class="c">#safeNumberFormat(disk_used_prod,"0")#</td>
</tr>
</cfoutput>
</table>
+5
View File
@@ -0,0 +1,5 @@
<cfdump var=#{
"Template Charset (File compilation)": getPageContext().getConfig().getTemplateCharset(),
"Web Charset (Forms, URLs, Responses)": getPageContext().getConfig().getWebCharset(),
"Resource Charset (File system reads/writes)": getPageContext().getConfig().getResourceCharset()
}#/>
+2 -2
View File
@@ -85,7 +85,7 @@
<div class="tr">
<div class="th">__name</div>
<div class="td">#d.__name# <a href="contragent_rpt.cfm?__id=#d.__id#&#tr.fwx#">Сводка по потреблению</a></div></div>
<div class="td">#d.__name# <a href="contragent_rpt.cfm?__id=#d.__id#&#tr.fwx#">Сводка по потреблению</a></div>
</div>
<div class="tr">
@@ -246,7 +246,7 @@
<cfcase value=3>-m</cfcase>
</cfswitch> --->
</td>
<td class="c">#type#</td>
<td class="c"<cfif type EQ 3> style="background:lightgreen"</cfif>>#type#</td>
<td class="c">#is_actual#</td>
<td class="c">#hash#</td>
<td class="c">#version#</td>
+26 -20
View File
@@ -62,6 +62,7 @@
<cfif len(d.__id)>
<b>#d.__name#</b>
[#d.__id#]
<b>#d.id_klienta#</b>
</cfif>
</cfoutput>
</layout:attribute>
@@ -235,7 +236,7 @@
<!--- <cfdump var=#qService#/> --->
<cfoutput>
<h3>Услуги по данным CRM (версии строк спецификации, только актуальные на сегодня, сделки с вероятностью от 50% (начиная с тестирования) <!--- (#qService.recordCount#) ---></h3>
<h3>Услуги по данным CRM (из DWH, версии строк спецификации, только актуальные на сегодня, сделки с вероятностью от 50% (начиная с тестирования) <!--- (#qService.recordCount#) ---></h3>
</cfoutput>
@@ -259,13 +260,13 @@
</thead>
<cfoutput query="qService" group="siv_uid">
<tr<cfif NOT left(abstractive_service_code,4) EQ "iaas"> class="gray"</cfif>>
<tr<cfif NOT (left(abstractive_service_code,4) EQ "iaas" OR left(abstractive_service_code,7) EQ "paas.s3")> class="gray"</cfif>>
<td class="c"><a href="deal_service.cfm?__id=#siv_uid#&#tr.fwx#">#siv_index#</a></td>
<td class="l">#abstractive_service_code#<cfif len(modifier_code)>.#modifier_code#</cfif></td>
<td class="l">#user_description#</td>
<td style="padding:0; vertical-align:bottom;">
<table class="wide" style="height:100%">
<cfset cost=0/>
<cfset cost = 0/>
<cfoutput group="p_uid">
<cfif p_cnt NEQ 0>
<tr>
@@ -283,7 +284,7 @@
<td class="c">#cnt#</td>
<td class="r">#nFmt(cost*cnt*(100-(isNumeric(discount)?discount:0))/100)#</td>
<td class="c">
<td class="c"<cfif line_pricing_model_id EQ 3> style="background:lightgreen;color:black;"</cfif>>
<cfswitch expression=#line_pricing_model_id#>
<cfcase value=1>install</cfcase>
<cfcase value=2>fix</cfcase>
@@ -301,6 +302,7 @@
</cfoutput>
</table>
<!--- <i>отображаются позиции сделок, начиная с тестирования</i> --->
<h2>Текущее потребление по данным VmReports (VROPS)</h1>
<cfquery name="qCompute">
select
@@ -309,18 +311,19 @@
,c."VDC"
,c."VDC_CPU_Reserv"
,"Cluster"
, round(sum(c."VM_RAM_Allocated")) as ram
, round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_RAM_Allocated" ELSE 0 END)) as ram_on
, round(sum(c."VM_vCPU_count")) as cpu
, round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_vCPU_count" ELSE 0 END)) as cpu_on
, round(avg(c."VDC_CPU_Speed")::numeric,1) as ghz
,round(sum(c."VM_RAM_Allocated")) as ram
,round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_RAM_Allocated" ELSE 0 END)) as ram_on
,round(sum(c."VM_vCPU_count")) as cpu
,round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_vCPU_count" ELSE 0 END)) as cpu_on
,round(avg(c."VDC_CPU_Speed")::numeric,1) as ghz
,min(c.ts) as ts
FROM vmreports.compute c
WHERE ts=(select max(ts) from vmreports.compute)
WHERE c.ts=(select max(ts) from vmreports.compute)
AND lower(c."WZ")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>)
GROUP BY c."Organization_UUID", c."Organization", c."VDC", c."VDC_CPU_Reserv", c."Cluster"
</cfquery>
<cfquery name="qCompute_total" dbtype="query">
<cfquery name="qCompute_total" dbtype="query">
select
sum(ram) as ram
,sum(ram_on) as ram_on
@@ -329,7 +332,7 @@
FROM qCompute
</cfquery>
<h3>Compute факт</h3>
<h3>Compute факт <cfif len(qCompute.ts)><cfoutput>#dateFormat(qCompute.ts,'YYYY-MM-DD')# #timeFormat(qCompute.ts,'HH:MM:SS')#</cfoutput></cfif></h3>
<table class="worktable">
<thead>
<tr>
@@ -379,10 +382,11 @@
,"VDC"
,"Cluster"
,"Storage_Policy"
, round(sum(c."Disk_Allocated")) as disk_alloc
, round(sum(c."Disk_Used")) as disk_used
,round(sum(c."Disk_Allocated")) as disk_alloc
,round(sum(c."Disk_Used")) as disk_used
,min(c.ts) as ts
FROM vmreports.storage c
WHERE ts=(select max(ts) from vmreports.storage)
WHERE c.ts=(select max(ts) from vmreports.storage)
AND lower(c."WZ")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>)
GROUP BY c."Organization_UUID",c."Organization",c."VDC",c."Cluster",c."Storage_Policy"
</cfquery>
@@ -394,7 +398,7 @@
FROM qStorage
</cfquery>
<h3>Storage факт</h3>
<h3>Storage факт <cfif len(qStorage.ts)><cfoutput>#dateFormat(qStorage.ts,'YYYY-MM-DD')# #timeFormat(qStorage.ts,'HH:MM:SS')#</cfoutput></cfif></h3>
<table class="worktable">
<thead>
<tr>
@@ -435,18 +439,20 @@
,"OrgStatus"
,"OrgVDC"
,(select STRING_AGG(DISTINCT "Cluster",',') FROM vmreports.compute c
WHERE ts=(select max(ts) from vmreports.compute)
AND g."Org"=c."Organization") as org_cluster
WHERE ts=(select max(ts) from vmreports.compute)
AND g."Org"=c."Organization"
) as org_cluster
,"Name"
,"GPU"
,g.ts as ts
FROM vmreports.vm_gpu g
WHERE ts=(select max(ts) from vmreports.vm_gpu)
WHERE g.ts=(select max(ts) from vmreports.vm_gpu)
AND lower(g."ClientID")=lower(<cfqueryparam cfsqltype="cf_sql_varchar" value="#d.id_klienta#"/>)
</cfquery>
<h3>GPU факт</h3>
<h3>GPU факт <cfif len(qGpu.ts)><cfoutput>#dateFormat(qGpu.ts,'YYYY-MM-DD')# #timeFormat(qGpu.ts,'HH:MM:SS')#</cfoutput></cfif></h3>
<table class="worktable">
<thead>
<tr>
+21 -5
View File
@@ -111,6 +111,8 @@ AS (
,round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_RAM_Allocated" ELSE 0 END)) AS ram_on
,round(sum(c."VM_vCPU_count")) AS cpu
,round(sum(CASE WHEN "VM_is_ON" > 0 THEN c."VM_vCPU_count" ELSE 0 END)) AS cpu_on
,STRING_AGG(DISTINCT "Organization_Status",',') as organization_status
,COUNT(DISTINCT "Organization_UUID") as org_count
FROM vmreports.compute c
WHERE ts = (
SELECT max(ts)
@@ -263,12 +265,21 @@ AS (
AND (<cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_report#/> < d.dt_next)
GROUP BY z.id_klienta
)
,manager AS (
select z.id_klienta as wz, u.__name as manager, u.email, u.__status_status as status
from elma.companies z
join elma.comp_users_ext u on (z.responsible=u.__id)
)
select
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
<d:field title="WZ Elma">r.wz as wz_sold</d:field>
<d:field title="Клиент">r.client as client_sold</d:field>
<d:field>r.company_uid</d:field>
<d:field title="WZ Cloud">a.wz as wz_alloc</d:field>
<d:field title="Manager">u.manager</d:field>
<d:field title="Manager Email">u.email</d:field>
<d:field title="Manager Status">u.status</d:field>
<d:field title="Статусы из VCD">a.organization_status</d:field><!--- список статусов через запятую --->
<d:field title="Статусы">ds.status_ids</d:field>
<d:field title="Модели оплаты">ds.line_pricing_model_ids</d:field>
<d:field title="Коды RAM">r.codes as ram_codes</d:field>
@@ -299,6 +310,7 @@ full join alloc a on (lower(r.wz)=lower(a.wz))
left join disk_alloc da on (a.wz=da.wz)
left join gpu_alloc ga on (a.wz=ga.wz)
left join elma.companies z on (lower(a.wz)=lower(z.id_klienta))
left join manager u on (lower(coalesce(r.wz,a.wz))=lower(u.wz))
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/>
</cfquery>
@@ -356,7 +368,9 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<th width="5%"><layout:column_head name="wz_sold"/></th>
<th width="10%"><layout:column_head name="client_sold"/></th>
<th width="5%"><layout:column_head name="wz_alloc"/></th>
<th width="5%"><layout:column_head name="manager"/></th>
<th width="3%"><layout:column_head name="status_ids"/></th>
<th width="5%"><layout:column_head name="organization_status"/></th>
<th width="3%"><layout:column_head name="line_pricing_model_ids"/></th>
<th width="10%"><layout:column_head name="cpu_codes"/></th>
@@ -395,25 +409,27 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
</cfif>
</td>
<td>#wz_alloc#</td>
<td><a href="mailto:#email#"<cfif qRead.status NEQ 2> title="не работает"</cfif>><span<cfif qRead.status NEQ 2> class="err"</cfif>>#manager#</span></a></td>
<td>#status_ids#</td>
<td>#organization_status#</td>
<td>#line_pricing_model_ids#</td>
<td>#cpu_codes#</td>
<td class="r"<cfif cpu_sold GT cpu_alloc> style="background:lightgreen;"</cfif>>#cpu_sold#</td>
<td class="r"<cfif len(wz_alloc)><cfif cpu_sold GT cpu_alloc> style="background:lightgreen;"</cfif><cfelse> style="background:yellow;"</cfif>>#cpu_sold#</td>
<td class="r"<cfif cpu_sold LT cpu_alloc> style="background:lightcoral;"</cfif>>#cpu_alloc#</td>
<td class="r"<cfif cpu_sold LT cpu_alloc_on> style="background:lightcoral;"</cfif>>#cpu_alloc_on#</td>
<td>#ram_codes#</td>
<td class="r"<cfif ram_sold GT ram_alloc> style="background:lightgreen;"</cfif>>#ram_sold#</td>
<td class="r"<cfif len(wz_alloc)><cfif ram_sold GT ram_alloc> style="background:lightgreen;"</cfif><cfelse> style="background:yellow;"</cfif>>#ram_sold#</td>
<td class="r"<cfif ram_sold LT ram_alloc> style="background:lightcoral;"</cfif>>#ram_alloc#</td>
<td class="r"<cfif ram_sold LT ram_alloc_on> style="background:lightcoral;"</cfif>>#ram_alloc_on#</td>
<td>#disk_codes#</td>
<td class="r"<cfif disk_sold GT disk_alloc> style="background:lightgreen;"</cfif>>#disk_sold#</td>
<td class="r"<cfif len(wz_alloc)><cfif disk_sold GT disk_alloc> style="background:lightgreen;"</cfif><cfelse> style="background:yellow;"</cfif>>#disk_sold#</td>
<td class="r"<cfif disk_sold LT disk_alloc> style="background:lightcoral;"</cfif>>#disk_alloc#</td>
<td>#gpu_codes#</td>
<td class="r"<cfif gpu_sold GT gpu_alloc> style="background:lightgreen;"</cfif>>#gpu_sold#</td>
<td class="r"<cfif len(wz_alloc)><cfif gpu_sold GT gpu_alloc> style="background:lightgreen;"</cfif><cfelse> style="background:yellow;"</cfif>>#gpu_sold#</td>
<td class="r"<cfif gpu_sold LT gpu_alloc> style="background:lightcoral;"</cfif>>#gpu_alloc#</td>
<td>#gpu#</td>
</tr>
@@ -436,7 +452,7 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<cfoutput query="qTotal">
<tr class="b r">
<td colspan="6">Итого</td>
<td colspan="7">Итого</td>
<td class="r"<cfif cpu_sold GT ram_alloc> style="background:lightgreen;"</cfif>>#cpu_sold#</td>
<td class="r"<cfif cpu_sold LT cpu_alloc> style="background:lightcoral;"</cfif>>#cpu_alloc#</td>
+7
View File
@@ -164,6 +164,13 @@ function roundSafe(a, precision) {
}
request.roundSafe = roundSafe;
function ceilingSafe(a) {
return (isNumeric(a)) ? ceiling(a) : a;
}
request.ceilingSafe = ceilingSafe;
function timeUnitLabel(n, value=0, locale="ru") {
var labels = ["сек.","мин.","ч.","д.","мес."];
if (n LE 5 AND n GE 1) {return labels[n];}
+188 -132
View File
@@ -7,18 +7,16 @@
<m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
<!---
<cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/>
<cfset hours=dateDiff('h',dt_start,dt_finish)/>
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/> --->
<cfparam name="dt_finish" type="date" default=#dateAdd('d',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
<cfset hours=dateDiff('h', dt_start, dateAdd('d', 1, dt_finish))/>
<cfparam name="only_articles_in_spec" type="boolean" default=false/>
<!--- Нужно еще применить политики бесплатного минимума --->
<!--- *** коды лучше взять из каталога --->
<cfquery name="qCode" datasource="dwh">
<cfquery name="qCode" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select distinct p.code
from elma.deals d
join elma.deals_services siv on (d.__id=ANY(siv.deal))
@@ -29,22 +27,28 @@
where p.type=3 AND aa.is_actual
order by p.code
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfoutput>qCode:#getTickCount()-request.startTickCount#</cfoutput>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<!--- <cfdump var=#qCode#/> --->
<cfquery name="qContragent" datasource="dwh">
<cfquery name="qContragent" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select k.id_klienta as wz, k.__id::text as contragent_uid, k.__name as contragent
from elma.companies k
where k."__deletedAt" IS NULL
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfoutput>qContragent:#getTickCount()-request.startTickCount#</cfoutput>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<!--- <cfif isDefined("DEBUG")>
<cfdump var=#qContragent#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif> --->
<!--- нужны компании, которые есть в пейге --->
<cfquery name="qSpec" datasource="dwh">
<cfquery name="qSpec" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select k.id_klienta as wz, k.__id::text as contragent_uid, p.code, p.price, p.discount, k.__name as contragent, a.__name as contract, a.__id::text as contract_uid, d.__name as deal, d.__id::text as deal_uid, siv.abstractive_service as abstract_service, siv.modifier, siv.user_description, siv.hash as line_key
,siv.date_nop as dt_from, siv.date_end as dt_to
/*,p.__name as line_key*/, p.ed_izm, p.name as component, aa.__name as additional_agreement, aa.__id::text as additional_agreement_uid
,siv.date_nop as dt_from, siv.date_end as dt_to, siv.discount as service_discount, siv.cnt as service_quantity
/*,p.__name as line_key*/, p.ed_izm, p.name as component, p.type, aa.__name as additional_agreement, aa.__id::text as additional_agreement_uid
--, aa.is_actual
from elma.deals d
join elma.deals_services siv on (d.__id=ANY(siv.deal))
@@ -52,35 +56,34 @@
join elma.companies k on (d._companies=k.__id)
join elma.additional_agreements aa on (aa.__id = ANY(siv.additional_agreement))
join elma.aggrements a on (aa.contract_uid = a.__id)
where p.type=3 AND aa.is_actual
where p.type IN (2,3) AND aa.is_actual
AND siv.date_nop < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND (siv.date_end > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR siv.date_end IS NULL)
AND (siv.date_end > <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/> OR siv.date_end IS NULL)/*****/
order by k.id_klienta, p.code
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- siv means specification item version --->
<cfquery name="qSivAge" datasource="dwh">
select max(dt_load) as dt_load from elma.deals_services
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<!--- здесь имеем список кодов с ценами и WZ. Каждому коду можно поставить в соответствие запрос, который даст по нему выборку. Изредка один запрос может вывести 2 кода, но разбить на 2 запроса легко. Кроме того, запросы можно объединить через union в один - может быть, так будет лучше читаться (быстрее выполняться не будет) --->
<cfoutput>qSpec:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfdump var=#qSpec#/>
<cfflush/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<!--- siv means specification item version --->
<cfquery name="qSivAge" datasource="dwh" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(dt_load) as dt_load from elma.deals_services
</cfquery>
<cfoutput>qSivAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfquery name="qComputing" datasource="billing-vc">
<cfquery name="qComputing" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select m.clientid as wz, vdc.name as vdc_name,
case
when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29'
when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31'
when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28'
when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28'
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
WHEN vdc.name LIKE '%-v1cl5%' THEN 'iaas.ngc.a45'
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера
else '['||vdc.name||']' end as code,
sum(cpu_used/cpu_speed)/4. as core_h,
sum(mem_used)/1024/4. as gb_h
@@ -95,43 +98,46 @@
left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.id)
where length(m.clientid) > 0
AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/>
group by m.clientid, vdc.name
order by m.clientid, vdc.name;
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfoutput>qComputing:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfdump var=#qComputing#/>
<cfflush/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<cfquery name="qComputingAge" datasource="billing-vc">
<cfquery name="qComputingAge" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfoutput>qComputingAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
<cfquery name="qStorage" datasource="billing-vc">
<cfquery name="qStorage" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select m.clientid as wz, vdc.name as vdc_name,
case
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
WHEN vdc.name LIKE '%-v1cl5%' THEN 'iaas.ngc.a45'
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера
ELSE '['||vdc.name||']' END
|| CASE
WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m'
WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m'
WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m'
WHEN storage_profile_types.name ILIKE '%FASTSSD%' THEN '.fstssd-m'
WHEN storage_profile_types.name ILIKE '%SSD%' THEN '.ssd-m'
WHEN storage_profile_types.name ILIKE '%SAS%' THEN '.sas-m'
WHEN storage_profile_types.name ILIKE '%SATA%' THEN '.sata-m'
ELSE '.['|| storage_profile_types.name ||']' END
as code,
storage_profile_types.name, -- *** это не тип, а профайл
sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут
sum(used)/1024./4 as gb_h_used
sum("limit")/1024./4./720. as gb_m_limit, -- 4 потому, что сбор раз в 15 минут
sum(used)/1024./4./720. as gb_m_used -- 720 это количество часов в условном месяце
from ngcloud_ru.capacity_storage
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id
join ngcloud_ru.tenant t on t.id=vdc.tenant_id
@@ -144,30 +150,30 @@
join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id
where length(m.clientid) > 0
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/>
group by m.clientid, vdc.name, storage_profile_types.name
order by m.clientid, vdc.name, storage_profile_types.name;
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qStorageAge" datasource="billing-vc">
select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
</cfquery>
<cfoutput>qStorage:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfdump var=#qStorage#/>
<cfflush/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qStorageAge" datasource="billing-vc" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
</cfquery>
<cfoutput>qStorageAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<!---
"placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb"
HOT_FREE_LIMIT 1 10 1 100
--->
<!--- надо дисконтировать не ГБ-часы а ГБ-месяцы --->
<cfquery name="qS3Vol" datasource="billing-s3">
<cfquery name="qS3Vol" datasource="billing-s3" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */
(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>) as vol_B
,ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>/1024/1024/1024) as vol_GB
@@ -178,7 +184,7 @@ HOT_FREE_LIMIT 1 10 1 100
when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
--,bucket_stat.placement_id
,bucket_stat.placement_id
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
from s3billing.bucket_stat
@@ -186,23 +192,23 @@ HOT_FREE_LIMIT 1 10 1 100
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
where bucket_stat.placement_id in (1,2)
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/>
group by bucket_stat.owner, bucket_stat.placement_id
order by bucket_stat.owner, bucket_stat.placement_id;
</cfquery>
<cfoutput>qS3Vol:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfdump var=#qS3Vol#/>
<cfflush/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfquery name="qS3VolAge" datasource="billing-s3">
<cfquery name="qS3VolAge" datasource="billing-s3" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(timestamp_addition) as dt_load from s3billing.bucket_stat
</cfquery>
<cfoutput> #getTickCount()-request.startTickCount#</cfoutput><cfflush/>
<cfoutput>qS3VolAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfquery name="qS3OpsTrf" datasource="billing-s3">
select
@@ -274,59 +280,91 @@ select
join s3billing.placement on bucket_info.placement_id=placement.id
where 1=1
AND usage_bucket_by_user.time >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_finish#/>
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/>
group by user_info.name, bucket_info.placement_id
order by user_info.name, bucket_info.placement_id;
</cfquery>
<cfoutput>qS3OpsTrf:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfdump var=#qS3OpsTrf#/>
<cfflush/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<cfquery name="qS3OpsTrfAge" datasource="billing-s3">
<cfquery name="qS3OpsTrfAge" datasource="billing-s3" cachedWithin=#createTimeSpan(0, 0, 25, 0)#>
select max(time) as dt_load from s3billing.usage_bucket_by_user
</cfquery>
<cfoutput>qS3OpsTrfAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfquery name="qUnifiedMetric" dbType="query">
select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric from qComputing
select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric, 'core-h' as unit
from qComputing
union all
select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing
select wz, code || '.ram-m', gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric, 'GByte-h' as unit
from qComputing
union all
select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage
select wz, code, gb_m_used as raw_metric, gb_m_used as metric, gb_m_used as chargeable_metric, 'GByte-m' as unit
from qStorage
union all
select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric from qS3Vol
select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric, 'GByte-m' as unit
from qS3Vol
union all
select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf
select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric, '10k' as unit
from qS3OpsTrf
union all
select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf
select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric, '10k' as unit
from qS3OpsTrf
union all
select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric from qS3OpsTrf
select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric, 'GByte' as unit
from qS3OpsTrf
order by wz, code
</cfquery>
<cfoutput>qUnifiedMetric:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfdump var=#qUnifiedMetric#/>
<cfflush/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<cfquery name="qChargeInner" dbType="query">
<cfset db = new MemoryDbHelper()/>
<cfset db.register("qUnifiedMetric", qUnifiedMetric, "inmem")/>
<cfset db.register("qContragent", qContragent, "inmem")/>
<cfset db.register("qSpec", qSpec, "inmem")/>
<cfquery name="qCharge" datasource="inmem">
SELECT
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
<d:field title="WZ">c.wz</d:field>
<d:field title="Артикул">m.code</d:field>
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
<d:field title="WZ">coalesce(coalesce(c.wz, m.wz), s.wz) as wz</d:field>
<d:field title="Артикул">coalesce(m.code, s.code) as code</d:field>
<d:field title="Артикул фикс">f.code as f_code</d:field>
<d:field title="Кол-во к оплате" cfSqlType="CF_SQL_NUMERIC">ceiling(m.chargeable_metric) as chargeable_metric</d:field>
<d:field title="Ед.изм.">m.unit</d:field>
<d:field title="Ед.изм.">s.ed_izm</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.price*(100-s.discount)/100 as discounted_price</d:field>
<d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.price*(100-s.discount)/100*m.chargeable_metric as charge</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.service_quantity*(100-s.service_discount)/100*s.price*(100-s.discount)/100 as discounted_price</d:field>
<d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.service_quantity*(100-s.service_discount)/100*s.price*(100-s.discount)/100*ceiling(m.chargeable_metric) as charge</d:field>
<d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">s.dt_from</d:field>
<d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">s.dt_to</d:field>
<d:field title="Ключ строки">s.line_key</d:field>
<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</d:field>
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">s.discount</d:field>
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведен&shy;ная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="contragent_uid">c.contragent_uid</d:field>
<d:field title="Приведенная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
<d:field title="Контрагент">coalesce(c.contragent,cs.contragent) as contragent</d:field>
<d:field title="contragent_uid">coalesce(c.contragent_uid,cs.contragent_uid) as contragent_uid</d:field>
<d:field title="Договор">s.contract</d:field>
<d:field title="contract_uid">s.contract_uid</d:field>
<d:field title="Допник">s.additional_agreement</d:field>
@@ -338,49 +376,30 @@ SELECT
<d:field title="Компонент">s.component</d:field>
<d:field title="Клиентс. назв.">s.user_description</d:field>
</d:field_set>
FROM qUnifiedMetric m, qContragent c, qSpec s WHERE m.wz=c.wz AND m.wz=s.wz AND m.code=s.code
FROM qUnifiedMetric m
FULL JOIN qSpec s ON (m.wz=s.wz AND m.code=s.code)
LEFT JOIN qSpec f ON (m.wz=f.wz AND m.code=f.code AND f.type=2)
LEFT JOIN qContragent c ON (m.wz=c.wz)
LEFT JOIN qContragent cs ON (s.wz=cs.wz) -- неуклюже, но иначе контрагент теряется
WHERE 1=1 AND s.type=3
<cfif only_articles_in_spec>
AND EXISTS(select * from qSpec qs where qs.wz=m.wz AND qs.type=3)
</cfif>
--AND s.wz='WZ01762'
<!---
AND 1=0
--->
ORDER BY wz,code
</cfquery>
<cfquery name="qChargeOuter" dbType="query">
SELECT
<d:field_set titleMapOut="titleMap_" lengthOut="fieldCount_">
<d:field title="WZ">c.wz</d:field>
<d:field title="Артикул">m.code</d:field>
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
<d:field title="Ед.изм.">null as ed_izm</d:field>
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">null discounted_price</d:field>
<d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">0 as charge</d:field>
<d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">null as dt_from</d:field>
<d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">null as dt_to</d:field>
<d:field title="Ключ строки">null as line_key</d:field>
<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">null as price</d:field>
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">null as discount</d:field>
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
<d:field title="Приведен&shy;ная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
<d:field title="Контрагент">c.contragent</d:field>
<d:field title="contragent_uid">c.contragent_uid</d:field>
<d:field title="Договор">null as contract</d:field>
<d:field title="contract_uid">null as contract_uid</d:field>
<d:field title="Допник">null as additional_agreement</d:field>
<d:field title="additional_agreement_uid">null as additional_agreement_uid</d:field>
<d:field title="Сделка">null as deal</d:field>
<d:field title="deal_uid">null as deal_uid</d:field>
<d:field title="Абстрактная услуга">null as abstract_service</d:field>
<d:field title="Модификатор">null as modifier</d:field>
<d:field title="Компонент">null as component</d:field>
<d:field title="Клиентс. назв.">null as user_description</d:field>
</d:field_set>
FROM qUnifiedMetric m, qContragent c WHERE m.wz=c.wz AND m.wz NOT IN (#listQualify(listRemoveDuplicates(ValueList(qChargeInner.wz)),"'")#)
</cfquery>
<!--- <cfdump var=#qCharge#/> --->
<cfquery name="qCharge" dbType="query">
select * from qChargeInner
union
select * from qChargeOuter
order by wz,code
</cfquery>
<!--- QoQ does not support join syntax, at least of Lucee 5.4--->
<cfoutput>qCharge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<!--- <cfdump var=#qCharge#/> --->
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<cfif isDefined("output_xls")>
@@ -401,6 +420,8 @@ order by wz,code
</layout:attribute>
</layout:page>
Факт потребления по основной базе биллинга, спецификации из DWH. Без детализации по бакетам, VDC и т.д.
Все запросы кэшированы на 25 минут.<br/>
Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) должен выполняться в бухгалтерской программе.
<b>Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную</b>
<br/>
@@ -409,6 +430,7 @@ order by wz,code
<form method="post" action="">
Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/>
по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/>
Только PAYG <input type="checkbox" name="only_articles_in_spec" value="1"<cfif only_articles_in_spec> checked</cfif>/>
<input type="submit" style="cursor:pointer;"/>
<input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/>
</form>
@@ -460,20 +482,24 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<cfset var acc=0/>
<tr>
<td bgcolor="##ccc"></td>
<td bgcolor="##ccc" colspan="5" class="b"><a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a> #contragent#</td>
<td bgcolor="##ccc" colspan="5" class="b">
<a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a>
#contragent#
<a href="contragent_rpt.cfm?__id=#contragent_uid#&#tr.fwx#">(сводка)</a>
</td>
<td></td>
<td bgcolor="##ccc" colspan="99"></td>
</tr>
<cfoutput>
<cfset acc=acc+charge/>
<tr>
<cfset acc += (isNumeric(charge)) ? charge : 0/>
<tr<cfif !len(unit)> class="gray"</cfif>>
<td>#currentRow#</a></td>
<td>#code#</td>
<td class="r" style="font-size:120%; padding:0 1em;">#chargeable_metric#</td>
<td class="c" style="font-size:90%;">#ed_izm#</td>
<td class="r">#discounted_price#</td>
<td class="r">#charge#</td>
<td>#code# <cfif !len(metric) and len(f_code)>(#f_code#)</cfif></td>
<td class="r" style="font-size:120%; padding:0 1em;">#request.roundSafe(chargeable_metric,3)#</td>
<td class="c" style="font-size:90%;">#len(unit)?unit:'['& ed_izm &']'#</td>
<td class="r">#gaussianRoundSafe(discounted_price,2)#</td>
<td class="r">#gaussianRoundSafe(charge,2)#</td>
<td></td>
@@ -481,15 +507,15 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<td>#component#</td>
<td>#user_description#</td>
<td class="r">#price#</td>
<td class="r">#gaussianRoundSafe(price,2)#</td>
<td class="r">#discount#</td>
<td class="r">#dateFormat(dt_from,'YYYY-MM-DD')#</td>
<td class="r">#dateFormat(dt_to,'YYYY-MM-DD')#</td>
<td class="r">#line_key#</td>
<td class="r" style="color:##bbb">#raw_metric#</td>
<td class="r">#metric#</td>
<td class="r" style="color:##bbb">#request.roundSafe(raw_metric,3)#</td>
<td class="r">#request.roundSafe(metric,3)#</td>
<td><a href="contract.cfm?__id=#contract_uid#&#tr.fwx#">#contract#</a></td>
<td><a href="additional_agreement.cfm?__id=#additional_agreement_uid#&#tr.fwx#">#additional_agreement#</a></td>
<td><a href="deal.cfm?__id=#deal_uid#&#tr.fwx#">#deal#</a></td>
@@ -498,7 +524,7 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<tr>
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
<td bgcolor="##eee" colspan="4" class="r" style="border-bottom:2px solid gray;"><b>Итого</b> <a href="contragent.cfm?__id=#contragent_uid#&#tr.fwx#">#wz#</a> #contragent#:</td>
<td bgcolor="##eee" colspan="1" class="r b" style="border-bottom:2px solid gray;">#NumFmt(acc,2)#</td>
<td bgcolor="##eee" colspan="1" class="r b nw" style="border-bottom:2px solid gray;">#NumFmt(acc,2)#</td>
<td colspan="14" style="border-bottom:2px solid gray;"></td>
</tr >
</cfoutput>
@@ -506,6 +532,9 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
</table>
<!--- <cfdump var=#qCharge#/> --->
<cfdump var=#this.datasources[request.ds].connectionString#/>
<cfdump var=#this.datasources["billing-vc"].connectionString#/>
<cfdump var=#this.datasources["billing-s3"].connectionString#/>
<layout:page section="footer"/>
@@ -520,3 +549,30 @@ left outer join
from ngcloud_ru.tenant_metadata) tm
on (t.id = tm.tenant_id AND tm.rn = 1)
left outer join ngcloud_ru.metadata m on (tm.metadata_id=m.id) --->
<cfscript>
string function gaussianRoundSafe(any num, numeric precision = 0, string default="") {
return (isNumeric(arguments.num)) ? gaussianRound(arguments.num, arguments.precision) : arguments.default;
}
function gaussianRound(numeric number, numeric precision = 0) {
var factor = 10 ^ precision;
var scaledNumber = number * factor;
var absScaled = abs(scaledNumber);
var sign = sgn(scaledNumber);
var floored = int(absScaled);
// If it's not ending in exactly .5, use standard rounding or precision scaling
if (absScaled - floored != 0.5) {
return round(number * factor) / factor;
}
// If it is exactly .5, round towards the nearest even number
if (floored % 2 != 0) {
// Nearest even is UP
return (floored + 1) * sign / factor;
} else {
// Nearest even is DOWN
return floored * sign / factor;
}
}
</cfscript>
+20
View File
@@ -0,0 +1,20 @@
<cfquery name="qEq" datasource="cmdb">
select svc_id,svc,descr,dt_created,creator_id,DT_UPDATED, UPDATER_ID, IS_PRODUCTION_READY, CODE, MAN SVC_SHORT, RESOURCE_REALM_TYPE_ID, VERSION ,ORCHESTRATOR_NAME, SORT, SVC_GROUP_ID, ICON_SRC, SYNONYMS from svc limit 100;
</cfquery>
<!--- <cfdump var=#qEq#/> --->
<!--- <cfquery name="qt" datasource="inmem">
SELECT CURRENT_DATE FROM (VALUES(0));
</cfquery>
<cfdump var=#qt#/>--->
<cfset db = new MemoryDbHelper()/>
<!--- <cfset db.drop("eq")/> --->
<cfset db.register("eq", qEq, "inmem")/>
<cfquery name="qTest" datasource="inmem">
select * from eq
</cfquery>
<!---
<cfset db.drop("eq")/> --->
<cfdump var=#qTest#/>
+9 -10
View File
@@ -70,24 +70,24 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
</cfoutput>
<cfoutput><b>#qVM.recordCount#</b></cfoutput>
<table class="worktable">
<table class="worktable" style="word-break:break-word">
<thead>
<tr>
<th width="5%">WZ</th>
<th width="3%">WZ</th>
<th width="5%">Имя</th>
<th width="5%">Уникальное имя</th>
<th width="7%">Уникальное имя</th>
<th width="3%">Organization</th>
<th width="3%">VDC</th>
<th width="5%">VDC</th>
<th width="3%">VDC CPU Reserv</th>
<th width="3%">VDC CPU Speed GHz</th>
<th width="3%">Cluster</th>
<th width="3%">Host</th>
<th width="7%">Host Model</th>
<th width="7%">CPU Model</th>
<th width="5%">Host Model</th>
<th width="5%">CPU Model</th>
<th width="3%">Host CPU Cores</th>
<th width="3%">Host CPU Sockets</th>
<th width="3%">Host CPU Speed GHz</th>
@@ -104,17 +104,16 @@ S3 операции и трафик: <b>#dateFormat(qS3OpsTrfAge.dt_load,'YYYY-M
<th width="3%">VM RAM Allocated GB</th>
<th width="3%">VM RAM Used GB</th>
<th width="3%">VM is ON</th>
<th width="2%">VM is ON</th>
</tr>
</thead>
<!--- <a href="contragent_rpt.cfm?__id=#company_uid#&#tr.fwx#" style="float:right;word-break:normal;" >--->
<cfoutput query="qVM">
<tr>
<td><a href="contragent.cfm?__id=#company_uid#&#tr.fwx#">#WZ#</a><a href="contragent_rpt.cfm?__id=#company_uid#&#tr.fwx#" style="float:right"><img src="img/view.gif" title="сводка по контрагенту"/></a></td>
<td><a href="contragent.cfm?__id=#company_uid#&#tr.fwx#"style="word-break:normal;">#WZ#&nbsp;<img src="img/view.gif" title="сводка по контрагенту" style="display:inline;"/></a></td>
<td>#Name#</td>
<td>#UUID_VM#</td>
<td>#Organization#</td>