Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Uptime tracking capability #1091

Merged
merged 2 commits into from
Apr 26, 2024
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
16 changes: 16 additions & 0 deletions app/controllers/api/connect/v3/systems/systems_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ class Api::Connect::V3::Systems::SystemsController < Api::Connect::BaseControlle
before_action :authenticate_system

def update
if params[:online_at].present?
params[:online_at].each do |online_at|
dthours = online_at.split(':')
if dthours.count == 2
begin
@system_uptime = SystemUptime.create!(system_id: @system.id, online_at_day: dthours[0], online_at_hours: dthours[1])
logger.debug(N_("Added uptime information for system '%s'") % @system.id)
rescue ActiveRecord::RecordNotUnique
logger.debug(N_("Uptime information existing for system '%s'") % @system.id)
end
else
logger.error(N_("Uptime data is malformed '%s'") % online_at)
end
end
end

@system.hostname = params[:hostname]

# Since the payload is handled by rails all values are converted to string
Expand Down
1 change: 1 addition & 0 deletions app/models/system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class System < ApplicationRecord
has_many :services, through: :activations
has_many :repositories, -> { distinct }, through: :services
has_many :products, -> { distinct }, through: :services
has_many :system_uptimes, dependent: :destroy

validates :system_token, uniqueness: { scope: %i[login password], case_sensitive: false }

Expand Down
7 changes: 7 additions & 0 deletions app/models/system_uptime.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class SystemUptime < ApplicationRecord
belongs_to :system

validates :system_id, presence: true
validates :online_at_day, presence: true
validates :online_at_hours, presence: true
end
18 changes: 18 additions & 0 deletions db/migrate/20240111200053_create_system_uptimes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class CreateSystemUptimes < ActiveRecord::Migration[6.1]
def change
safety_assured do
create_table :system_uptimes do |t|
t.bigint :system_id, null: false
t.date :online_at_day, null: false
t.column :online_at_hours, 'binary(24)', null: false
t.timestamps
end

commit_db_transaction

add_index :system_uptimes, %i[system_id online_at_day], unique: true, name: 'id_online_day'

add_foreign_key :system_uptimes, :systems, column: :system_id, validate: false
end
end
end
10 changes: 10 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@
t.index ["regcode"], name: "index_subscriptions_on_regcode"
end

create_table "system_uptimes", charset: "utf8mb3", collation: "utf8mb3_general_ci", force: :cascade do |t|
t.bigint "system_id", null: false
t.date "online_at_day", null: false
t.binary "online_at_hours", limit: 24, null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["system_id", "online_at_day"], name: "id_online_day", unique: true
end

create_table "systems", charset: "utf8", force: :cascade do |t|
t.string "login"
t.string "password"
Expand Down Expand Up @@ -180,4 +189,5 @@
add_foreign_key "repositories_services", "services", on_delete: :cascade
add_foreign_key "services", "products"
add_foreign_key "subscription_product_classes", "subscriptions", on_delete: :cascade
add_foreign_key "system_uptimes", "systems"
end
15 changes: 15 additions & 0 deletions lib/suse/connect/system_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SUSE::Connect::SystemSerializer < ActiveModel::Serializer
attribute :hostname, if: :needs_full_update?
attribute :hwinfo, if: :has_hwinfo_and_needs_full_update?
attribute :products, if: :needs_full_update?
attribute :online_at, if: :has_system_uptime?

# We send the internal system id as system_token if the system (in RMT) is
# duplicated (therefore using the system_token mechanism).
Expand Down Expand Up @@ -47,6 +48,16 @@ def products
end
end

def online_at
object.system_uptimes.map do |system_uptime|
payload = {
online_at_day: system_uptime.online_at_day,
online_at_hours: system_uptime.online_at_hours
}
payload
end
end

def hwinfo
JSON.parse(object.system_information).symbolize_keys
end
Expand All @@ -59,6 +70,10 @@ def has_system_token?
object.system_token.present?
end

def has_system_uptime?
online_at.present?
end

def needs_full_update?
!object.scc_synced_at
end
Expand Down
8 changes: 8 additions & 0 deletions lib/tasks/system_uptimes.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace :db do
namespace :maintenance do
desc 'Delete all uptime tracking data which are older than 90 days'
task cleanup_uptime_tracking: :environment do
SystemUptime.where("online_at_day < '#{90.days.ago}'").delete_all
end
end
end
12 changes: 12 additions & 0 deletions package/files/systemd/rmt-uptime-cleanup.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Description=RMT uptime cleanup service
Requires=mysql.service
Wants=rmt-uptime-cleanup.timer

[Service]
Type=oneshot
WorkingDirectory=/usr/share/rmt/bin
ExecStart=bundle exec rake db:maintenance:cleanup_uptime_tracking RAILS_ENV=production

[Install]
WantedBy=multi-user.target
10 changes: 10 additions & 0 deletions package/files/systemd/rmt-uptime-cleanup.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
Description=RMT Uptime Data cleanup timer

[Timer]
# Run this timer every day at a randomized 24h delay.
OnCalendar=weekly
RandomizedDelaySec=24h

[Install]
WantedBy=timers.target
20 changes: 20 additions & 0 deletions package/obs/rmt-server.changes
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Thu April 18 09:27:00 UTC 2024 - Adnilson Delgado <[email protected]>
- Version 2.17 :
* Improve CLI mirroring summary information by adding the mirror repositories, the file count and size. This fixes issue #702.

-------------------------------------------------------------------
Thu April 17 15:22:00 UTC 2024 - Yogalakshmi Arunachalam <[email protected]>

- Adding Uptime tracking capability
* Uptime data is included in the data sent to SCC via RMT
yarunachalam marked this conversation as resolved.
Show resolved Hide resolved
* https://jira.suse.com/browse/PED-7982
* https://jira.suse.com/browse/PED-8018

-------------------------------------------------------------------
Thu April 11 15:22:00 UTC 2024 - Felix Schnizlein <[email protected]>

Expand All @@ -12,6 +20,18 @@ Thu April 11 15:22:00 UTC 2024 - Felix Schnizlein <[email protected]>
directories are obsolete and can be removed savely.
* Add support for debian repositories using flat or nested structures (jsc#PED-3684)

-------------------------------------------------------------------
Thu April 07 13:23:00 UTC 2024 - Felix Schnizlein <[email protected]>

- Version 2.16 (unreleased):
* Support bzip2 compressed repositories (bsc#1222122)

-------------------------------------------------------------------
Thu Mar 07 15:33:00 UTC 2024 - Likhitha Priya <[email protected]>

- Version 2.16:
* Add support for debian repositories using flat or nested structures

-------------------------------------------------------------------
Wed Oct 04 13:23:00 UTC 2023 - Felix Schnizlein <[email protected]>

Expand Down
16 changes: 11 additions & 5 deletions package/obs/rmt-server.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#
# spec file for package rmt-server
#
# Copyright (c) 2023 SUSE LLC
# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
Expand Down Expand Up @@ -149,13 +149,15 @@ mkdir -p %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server-mirror.timer %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server-sync.timer %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server-systems-scc-sync.timer %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-uptime-cleanup.timer %{buildroot}%{_unitdir}

install -m 444 package/files/systemd/rmt-server-mirror.service %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server-sync.service %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server-systems-scc-sync.service %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server.service %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server.target %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-server-migration.service %{buildroot}%{_unitdir}
install -m 444 package/files/systemd/rmt-uptime-cleanup.service %{buildroot}%{_unitdir}

install -m 444 engines/registration_sharing/package/rmt-server-regsharing.service %{buildroot}%{_unitdir}
install -m 444 engines/registration_sharing/package/rmt-server-regsharing.timer %{buildroot}%{_unitdir}
Expand All @@ -168,6 +170,7 @@ ln -fs %{_sbindir}/service %{buildroot}%{_sbindir}/rcrmt-server-migration
ln -fs %{_sbindir}/service %{buildroot}%{_sbindir}/rcrmt-server-mirror
ln -fs %{_sbindir}/service %{buildroot}%{_sbindir}/rcrmt-server-sync
ln -fs %{_sbindir}/service %{buildroot}%{_sbindir}/rcrmt-server-systems-scc-sync
ln -fs %{_sbindir}/service %{buildroot}%{_sbindir}/rcrmt-uptime-cleanup

ln -fs %{_sbindir}/service %{buildroot}%{_sbindir}/rcrmt-server-regsharing
ln -fs %{_sbindir}/service %{buildroot}%{_sbindir}/rcrmt-server-trim-cache
Expand Down Expand Up @@ -274,6 +277,7 @@ chrpath -d %{buildroot}%{lib_dir}/vendor/bundle/ruby/*/extensions/*/*/mysql2-*/m
%{_sbindir}/rcrmt-server-sync
%{_sbindir}/rcrmt-server-mirror
%{_sbindir}/rcrmt-server-systems-scc-sync
%{_sbindir}/rcrmt-uptime-cleanup
%{_unitdir}/rmt-server.target
%{_unitdir}/rmt-server.service
%{_unitdir}/rmt-server-migration.service
Expand All @@ -283,6 +287,8 @@ chrpath -d %{buildroot}%{lib_dir}/vendor/bundle/ruby/*/extensions/*/*/mysql2-*/m
%{_unitdir}/rmt-server-sync.timer
%{_unitdir}/rmt-server-systems-scc-sync.service
%{_unitdir}/rmt-server-systems-scc-sync.timer
%{_unitdir}/rmt-uptime-cleanup.service
%{_unitdir}/rmt-uptime-cleanup.timer
%dir %{_datadir}/bash-completion/
%dir %{_datadir}/bash-completion/completions/
%{_datadir}/bash-completion/completions/rmt-cli
Expand Down Expand Up @@ -323,10 +329,10 @@ getent group %{rmt_group} >/dev/null || %{_sbindir}/groupadd -r %{rmt_group}
getent passwd %{rmt_user} >/dev/null || \
%{_sbindir}/useradd -g %{rmt_group} -s /bin/false -r \
-c "user for RMT" %{rmt_user}
%service_add_pre rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service
%service_add_pre rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service rmt-uptime-cleanup.service

%post
%service_add_post rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service
%service_add_post rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service rmt-uptime-cleanup.service

# Run only on install
if [ $1 -eq 1 ]; then
Expand Down Expand Up @@ -359,10 +365,10 @@ if [ ! -e %{_datadir}/rmt/public/suma ]; then
fi

%preun
%service_del_preun rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service
%service_del_preun rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service rmt-uptime-cleanup.service

%postun
%service_del_postun rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service
%service_del_postun rmt-server.target rmt-server.service rmt-server-migration.service rmt-server-mirror.service rmt-server-sync.service rmt-server-systems-scc-sync.service rmt-uptime-cleanup.service

%posttrans config
# Don't fail if either systemd or nginx are not running
Expand Down
7 changes: 7 additions & 0 deletions spec/factories/system_uptimes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FactoryBot.define do
factory :system_uptime do
association :system
sequence(:online_at_day) { Time.zone.now }
online_at_hours { '111111111111111111111111' }
end
end
6 changes: 6 additions & 0 deletions spec/factories/systems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,11 @@
trait :with_system_token do
sequence(:system_token) { |n| "00000000-0000-4000-9000-#{n.to_s.rjust(12, '0')}" }
end

trait :with_system_uptimes do
after :create do |system, _|
create(:system_uptime, system: system)
end
end
end
end
9 changes: 9 additions & 0 deletions spec/lib/suse/connect/system_serializer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,13 @@
expect(serializer.key? :system_token).to eq(false)
end
end

context 'system with systemuptime' do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also change the description but I don't see it as a blocker.

let(:system) { create :system, :with_system_uptimes }

it 'match systemuptime data' do
expect((serializer[:online_at][0][:online_at_day]).to_date).to eq(Time.zone.now.to_date)
expect((serializer[:online_at][0][:online_at_hours]).to_s).to eq('111111111111111111111111')
end
end
end
7 changes: 7 additions & 0 deletions spec/models/system_uptime_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'rails_helper'

RSpec.describe SystemUptime, type: :model do
it { is_expected.to validate_presence_of(:system_id) }
it { is_expected.to validate_presence_of(:online_at_day) }
it { is_expected.to validate_presence_of(:online_at_hours) }
end
37 changes: 37 additions & 0 deletions spec/requests/api/connect/v3/systems/systems_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
}
end
let(:payload) { { hostname: 'test', hwinfo: hwinfo } }
let(:system_uptime) { system.system_uptimes.first }
let(:online_hours) { ':111111111111111111111111' }

describe '#update' do
subject(:update_action) { put url, params: payload, headers: headers }
Expand Down Expand Up @@ -45,6 +47,41 @@
expect(information[:cpus]).to eq('16')
end
end

context 'when uptime data provided' do
let(:payload) { { hostname: 'test', hwinfo: hwinfo, online_at: [1.day.ago.to_date.to_s << online_hours] } }

it 'inserts the uptime data in system_uptimes table' do
update_action

expect(system_uptime.system_id).to eq(system.reload.id)
expect(system_uptime.online_at_day.to_date).to eq(1.day.ago.to_date)
expect(system_uptime.online_at_hours.to_s).to eq('111111111111111111111111')
end
end

context 'when same uptime data duplicated' do
let(:payload) { { hostname: 'test', hwinfo: hwinfo, online_at: [1.day.ago.to_date.to_s << online_hours, 1.day.ago.to_date.to_s << online_hours] } }

it 'avoids duplication if multiple records have same data' do
update_action

expect(system.system_uptimes.count).to eq(1)
expect(system_uptime.system_id).to eq(system.reload.id)
expect(system_uptime.online_at_day.to_date).to eq(1.day.ago.to_date)
expect(system_uptime.online_at_hours.to_s).to eq('111111111111111111111111')
end
end

context 'when uptime data is malformed' do
let(:payload) { { hostname: 'test', hwinfo: hwinfo, online_at: [1.day.ago.to_date.to_s] } }

it 'record is not inserted' do
update_action

expect(system.system_uptimes.count).to eq(0)
end
end
end

context 'when hostname is not provided' do
Expand Down