Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ public class GenerateUsageRecordsCmd extends BaseCmd {

@Parameter(name = ApiConstants.END_DATE,
type = CommandType.DATE,
required = true,
required = false,
description = "End date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.")
private Date endDate;

@Parameter(name = ApiConstants.START_DATE,
type = CommandType.DATE,
required = true,
required = false,
description = "Start date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.")
private Date startDate;

Expand Down
31 changes: 31 additions & 0 deletions ui/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@
"label.datetime.filter.starting": "Starting <b>{startDate}</b>.",
"label.datetime.filter.up.to": "Up to <b>{endDate}</b>.",
"label.day": "Day",
"label.days": "Days",
"label.day.of.month": "Day of month",
"label.day.of.week": "Day of week",
"label.db.usage.metrics": "DB/Usage server",
Expand Down Expand Up @@ -806,6 +807,7 @@
"label.done": "Done",
"label.down": "Down",
"label.download": "Download",
"label.download.csv": "Download CSV",
"label.download.kubeconfig.cluster": "Download kubeconfig for the cluster <br><br> The <code><b>kubectl</b></code> command-line tool uses kubeconfig files to find the information it needs to choose a cluster and communicate with the API server of a cluster.",
"label.download.kubectl": "Download <code><b>kubectl</b></code> tool for cluster's Kubernetes version",
"label.download.kubernetes.cluster.config": "Download Kubernetes cluster config",
Expand Down Expand Up @@ -924,6 +926,7 @@
"label.fetch.instances": "Fetch Instances",
"label.fetch.latest": "Fetch latest",
"label.filename": "File Name",
"label.fetched": "Fetched",
"label.files": "Alternate files to retrieve",
"label.filter": "Filter",
"label.filter.annotations.all": "All comments",
Expand Down Expand Up @@ -1229,6 +1232,8 @@
"label.label": "Label",
"label.last.updated": "Last update",
"label.lastannotated": "Last annotation date",
"label.lastheartbeat": "Last heartbeat",
"label.lastsuccessfuljob": "Last successful job",
"label.lastboottime": "Boot time of the management server machine",
"label.lastname": "Last name",
"label.lastname.lower": "lastname",
Expand Down Expand Up @@ -1483,6 +1488,7 @@
"label.no.items": "No available Items",
"label.no.matching.offering": "No matching offering found",
"label.no.matching.network": "No matching Networks found",
"label.no.usage.records": "No usage records found",
"label.noderootdisksize": "Node root disk size (in GB)",
"label.nodiskcache": "No disk cache",
"label.none": "None",
Expand Down Expand Up @@ -1523,6 +1529,7 @@
"label.of": "of",
"label.of.month": "of month",
"label.offerha": "Offer HA",
"label.offeringid": "Offering ID",
"label.offeringtype": "Compute offering type",
"label.ok": "OK",
"label.only.end.date.and.time": "Only end date and time",
Expand Down Expand Up @@ -1700,6 +1707,8 @@
"label.publicnetwork": "Public Network",
"label.publicport": "Public port",
"label.purgeresources": "Purge Resources",
"label.purge.usage.records.success": "Successfuly purged usage records",
"label.purge.usage.records.error": "Failed while purging usage records",
"label.purpose": "Purpose",
"label.qostype": "QoS type",
"label.quickview": "Quick view",
Expand Down Expand Up @@ -1731,7 +1740,14 @@
"label.rados.secret": "RADOS secret",
"label.rados.user": "RADOS user",
"label.ram": "RAM",
"label.range.today": "Today",
"label.range.yesterday": "Yesterday",
"label.range.last.1week": "Last 1 week",
"label.range.last.2week": "Last 2 weeks",
"label.range.last.1month": "Last 1 month",
"label.range.last.3month": "Last 3 months",
"label.raw.data": "Raw data",
"label.rawusage": "Raw usage (in hours)",
"label.rbd": "RBD",
"label.rbdid": "Cephx user",
"label.rbdmonitor": "Ceph monitor",
Expand Down Expand Up @@ -1975,6 +1991,7 @@
"label.sharedrouteripv6": "IPv6 address for the VR in this shared Network.",
"label.sharewith": "Share with",
"label.showing": "Showing",
"label.show.usage.records": "Show usage records",
"label.shrinkok": "Shrink OK",
"label.shutdown": "Shutdown",
"label.shutdown.provider": "Shutdown provider",
Expand Down Expand Up @@ -2283,8 +2300,22 @@
"label.upload.volume.from.url": "Upload volume from URL",
"label.url": "URL",
"label.usage.explanation": "Note: Only the usage server that owns the active usage job is shown here.",
"label.usage": "Usage",
"label.usage.records.downloading": "Downloading usage records",
"label.usage.records.fetch.child.domains": "Fetch usage records for child domains",
"label.usage.records.usagetype.required": "Usage type is required with resource ID",
"label.usage.records.generate": "Generate usage records",
"label.usage.records.generate.after": "Usage records will be created for the period after ",
"label.usage.records.generated": "A job has been created to generate usage records.",
"label.usage.records.generate.description": "If the scheduled usage job was not run or failed, this will generate records(only if there any records to be generated)",
"label.usage.records.purge": "Purge usage records",
"label.usage.records.purge.days": "Purge records older than",
"label.usage.records.purge.days.description": "Purge records older than the specified number of days.",
"label.usage.records.purge.alert": "Purging usage records will permanently delete the records from the database. Depending on the data being deleted, this can increase load on the database and may take a while. Are you sure you want to continue?",
"label.usageid": "Resource ID",
"label.usageinterface": "Usage interface",
"label.usagename": "Usage type",
"label.usagetype": "Usage type",
"label.usageunit": "Unit",
"label.usageislocal": "A Usage Server is installed locally",
"label.usagetypedescription": "Usage description",
Expand Down
49 changes: 47 additions & 2 deletions ui/src/components/view/ListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
:pagination="false"
:rowSelection="explicitlyAllowRowSelection || enableGroupAction() || $route.name === 'event' ? {selectedRowKeys: selectedRowKeys, onChange: onSelectChange, columnWidth: 30} : null"
:rowClassName="getRowClassName"
@resizeColumn="handleResizeColumn"
style="overflow-y: auto"
>
<template #customFilterDropdown>
Expand Down Expand Up @@ -98,6 +99,9 @@
<template v-if="column.key === 'templatetype'">
<span>{{ text }}</span>
</template>
<template v-if="column.key === 'templateid'">
<router-link :to="{ path: '/template/' + record.templateid }">{{ text }}</router-link>
</template>
<template v-if="column.key === 'type'">
<span v-if="['USER.LOGIN', 'USER.LOGOUT', 'ROUTER.HEALTH.CHECKS', 'FIREWALL.CLOSE', 'ALERT.SERVICE.DOMAINROUTER'].includes(text)">{{ $t(text.toLowerCase()) }}</span>
<span v-else>{{ text }}</span>
Expand Down Expand Up @@ -245,7 +249,7 @@
</template>
<template v-if="column.key === 'vpcname'">
<a v-if="record.vpcid">
<router-link :to="{ path: '/vpc/' + record.vpcid }">{{ text }}</router-link>
<router-link :to="{ path: '/vpc/' + record.vpcid }">{{ text || record.vpcid }}</router-link>
</a>
<span v-else>{{ text }}</span>
</template>
Expand Down Expand Up @@ -276,6 +280,9 @@
<template v-if="column.key === 'level'">
<router-link :to="{ path: '/event/' + record.id }">{{ text }}</router-link>
</template>
<template v-if="column.key === 'usageType'">
{{ usageTypeMap[record.usagetype] }}
</template>

<template v-if="column.key === 'clustername'">
<router-link :to="{ path: '/cluster/' + record.clusterid }">{{ text }}</router-link>
Expand Down Expand Up @@ -319,7 +326,7 @@
<span v-else>{{ text }}</span>
</template>
<template v-if="column.key === 'zone'">
<router-link v-if="record.zoneid && !record.zoneid.includes(',') && $router.resolve('/zone/' + record.zoneid).matched[0].redirect !== '/exception/404'" :to="{ path: '/zone/' + record.zoneid }">{{ text }}</router-link>
<router-link v-if="record.zoneid && !record.zoneid.includes(',') && $router.resolve('/zone/' + record.zoneid).matched[0].redirect !== '/exception/404'" :to="{ path: '/zone/' + record.zoneid }">{{ text || record.zoneid }}</router-link>
<span v-else>{{ text }}</span>
</template>
<template v-if="column.key === 'zonename'">
Expand Down Expand Up @@ -374,6 +381,9 @@
<template v-if="column.key === 'payloadurl'">
<copy-label :label="text" />
</template>
<template v-if="column.key === 'usageid'">
<copy-label :label="text" />
</template>
<template v-if="column.key === 'eventtype'">
<router-link v-if="$router.resolve('/event/' + record.eventid).matched[0].redirect !== '/exception/404'" :to="{ path: '/event/' + record.eventid }">{{ text }}</router-link>
<span v-else>{{ text }}</span>
Expand Down Expand Up @@ -406,6 +416,9 @@
<template v-if="column.key === 'duration' && ['webhook', 'webhookdeliveries'].includes($route.path.split('/')[1])">
<span> {{ getDuration(record.startdate, record.enddate) }} </span>
</template>
<template v-if="['startdate', 'enddate'].includes(column.key) && ['usage'].includes($route.path.split('/')[1])">
{{ $toLocaleDate(text.replace('\'T\'', ' ')) }}
</template>
<template v-if="column.key === 'order'">
<div class="shift-btns">
<a-tooltip :name="text" placement="top">
Expand Down Expand Up @@ -482,6 +495,13 @@
icon="reload-outlined"
:disabled="!('updateConfiguration' in $store.getters.apis)" />
</template>
<template v-if="column.key === 'usageActions'">
<tooltip-button
:tooltip="$t('label.view')"
icon="search-outlined"
@onClick="$emit('view-usage-record', record)" />
<slot></slot>
</template>
<template v-if="column.key === 'tariffActions'">
<tooltip-button
:tooltip="$t('label.edit')"
Expand Down Expand Up @@ -618,6 +638,7 @@ export default {
disable: 'storageallocateddisablethreshold'
}
},
usageTypeMap: {},
resourceIdToValidLinksMap: {}
}
},
Expand All @@ -632,6 +653,9 @@ export default {
}
}
},
created () {
this.getUsageTypes()
},
computed: {
hasSelected () {
return this.selectedRowKeys.length > 0
Expand Down Expand Up @@ -942,6 +966,9 @@ export default {
}
return name
},
handleResizeColumn (w, col) {
col.width = w
},
updateSelectedColumns (name) {
this.$emit('update-selected-columns', name)
},
Expand All @@ -965,6 +992,24 @@ export default {
}
var duration = Date.parse(enddate) - Date.parse(startdate)
return (duration > 0 ? duration / 1000.0 : 0) + ''
},
getUsageTypes () {
if (this.$route.path.split('/')[1] === 'usage') {
api('listUsageTypes').then(json => {
if (json && json.listusagetypesresponse && json.listusagetypesresponse.usagetype) {
this.usageTypes = json.listusagetypesresponse.usagetype.map(x => {
return {
id: x.usagetypeid,
value: x.description
}
})
this.usageTypeMap = {}
for (var usageType of this.usageTypes) {
this.usageTypeMap[usageType.id] = usageType.value
}
}
})
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions ui/src/components/widgets/Status.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ export default {
case 'InProgress':
state = this.$t('state.inprogress')
break
case 'Down':
state = this.$t('state.down')
break
case 'Up':
state = this.$t('state.up')
break
}
return state.charAt(0).toUpperCase() + state.slice(1)
}
Expand Down
1 change: 0 additions & 1 deletion ui/src/config/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ export function asyncRouterMap () {
generateRouterMap(tools),
generateRouterMap(quota),
generateRouterMap(cloudian),

{
path: '/exception',
name: 'exception',
Expand Down
8 changes: 8 additions & 0 deletions ui/src/config/section/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ export default {
}
]
},
{
name: 'usage',
title: 'label.usage',
icon: 'ContainerOutlined',
permission: ['listUsageRecords'],
meta: { title: 'label.usage', icon: 'ContainerOutlined' },
component: () => import('@/views/infra/UsageRecords.vue')
},
{
name: 'manageinstances',
title: 'label.action.import.export.instances',
Expand Down
2 changes: 2 additions & 0 deletions ui/src/core/lazy_lib/icons_use.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import {
ClusterOutlined,
CodeOutlined,
CompassOutlined,
ContainerOutlined,
ControlOutlined,
CopyOutlined,
CreditCardOutlined,
Expand Down Expand Up @@ -220,6 +221,7 @@ export default {
app.component('CloudUploadOutlined', CloudUploadOutlined)
app.component('ClusterOutlined', ClusterOutlined)
app.component('CodeOutlined', CodeOutlined)
app.component('ContainerOutlined', ContainerOutlined)
app.component('ControlOutlined', ControlOutlined)
app.component('CompassOutlined', CompassOutlined)
app.component('CopyOutlined', CopyOutlined)
Expand Down
24 changes: 24 additions & 0 deletions ui/src/utils/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,27 @@ export function sanitizeReverse (value) {
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
}

export function toCsv ({ keys = null, data = null, columnDelimiter = ',', lineDelimiter = '\n' }) {
if (data === null || !data.length) {
return null
}

let result = ''
result += keys.join(columnDelimiter)
result += lineDelimiter

data.forEach(item => {
keys.forEach(key => {
if (item[key] === undefined) {
item[key] = ''
}
result += typeof item[key] === 'string' && item[key].includes(columnDelimiter) ? `"${item[key]}"` : item[key]
result += columnDelimiter
})
result = result.slice(0, -1)
result += lineDelimiter
})

return result
}
2 changes: 1 addition & 1 deletion ui/src/views/AutogenView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ export default {
})
},
fetchData (params = {}) {
if (this.$route.name === 'deployVirtualMachine') {
if (['deployVirtualMachine', 'usage'].includes(this.$route.name)) {
return
}
if (this.routeName !== this.$route.name) {
Expand Down
27 changes: 2 additions & 25 deletions ui/src/views/iam/RolePermissionTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ import draggable from 'vuedraggable'
import PermissionEditable from './PermissionEditable'
import RuleDelete from './RuleDelete'
import TooltipButton from '@/components/widgets/TooltipButton'
import { toCsv } from '@/utils/util.js'

export default {
name: 'RolePermissionTab',
Expand Down Expand Up @@ -249,32 +250,8 @@ export default {
this.updateTable = false
})
},
rulesDataToCsv ({ data = null, columnDelimiter = ',', lineDelimiter = '\n' }) {
if (data === null || !data.length) {
return null
}

const keys = ['rule', 'permission', 'description']
let result = ''
result += keys.join(columnDelimiter)
result += lineDelimiter

data.forEach(item => {
keys.forEach(key => {
if (item[key] === undefined) {
item[key] = ''
}
result += typeof item[key] === 'string' && item[key].includes(columnDelimiter) ? `"${item[key]}"` : item[key]
result += columnDelimiter
})
result = result.slice(0, -1)
result += lineDelimiter
})

return result
},
exportRolePermissions () {
const rulesCsvData = this.rulesDataToCsv({ data: this.rules })
const rulesCsvData = toCsv({ keys: ['rule', 'permission', 'description'], data: this.rules })
const hiddenElement = document.createElement('a')
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(rulesCsvData)
hiddenElement.target = '_blank'
Expand Down
Loading