Skip to content

Commit 8cb391c

Browse files
committed
Address code review
* cpus is now a uint32 in multipass.proto * removed LinuxSystemInfo struct and replaced with two functions * get_cpus() and get_total_ram() are now platform functions with a linux implementation * configuring a VM's resources now uses daemonInfoProvider properly * cpu, ram, and disk sliders are no longer consumers
1 parent d29c1fe commit 8cb391c

File tree

13 files changed

+106
-133
lines changed

13 files changed

+106
-133
lines changed

include/multipass/platform.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class Platform : public Singleton<Platform>
7777
virtual QString default_privileged_mounts() const;
7878
virtual bool is_image_url_supported() const;
7979
[[nodiscard]] virtual std::string bridge_nomenclature() const;
80+
virtual int get_cpus() const;
81+
virtual long long get_total_ram() const;
8082
};
8183

8284
QString interpret_setting(const QString& key, const QString& val);

src/client/gui/lib/catalogue/launch_form.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ import '../vm_details/mount_points.dart';
1818
import '../vm_details/ram_slider.dart';
1919
import '../vm_details/spec_input.dart';
2020

21-
// Define the daemonInfoProvider here
22-
final daemonInfoProvider = FutureProvider.autoDispose<DaemonInfoReply>((ref) {
23-
return ref.watch(grpcClientProvider).daemonInfo();
24-
});
25-
2621
final launchingImageProvider = StateProvider<ImageInfo>((_) => ImageInfo());
2722

2823
final randomNameProvider = Provider.autoDispose(

src/client/gui/lib/providers.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ final daemonAvailableProvider = Provider((ref) {
7272
return false;
7373
});
7474

75+
final daemonInfoProvider = FutureProvider((ref) {
76+
return ref.watch(grpcClientProvider).daemonInfo();
77+
});
78+
7579
class AllVmInfosNotifier extends Notifier<List<DetailedInfoItem>> {
7680
@override
7781
List<DetailedInfoItem> build() {

src/client/gui/lib/vm_details/cpus_slider.dart

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,24 @@ import 'dart:math' as math;
22

33
import 'package:flutter/material.dart';
44
import 'package:flutter/services.dart';
5-
import 'package:flutter_riverpod/flutter_riverpod.dart';
65

7-
class CpusSlider extends ConsumerStatefulWidget {
6+
class CpusSlider extends StatefulWidget {
87
final int? initialValue;
98
final FormFieldSetter<int> onSaved;
10-
119
final int maxCpus;
1210

1311
const CpusSlider({
1412
super.key,
1513
this.initialValue,
1614
required this.onSaved,
17-
this.maxCpus=1,
15+
this.maxCpus = 1,
1816
});
1917

2018
@override
21-
ConsumerState<CpusSlider> createState() => _CpusSliderState();
19+
State<CpusSlider> createState() => _CpusSliderState();
2220
}
2321

24-
class _CpusSliderState extends ConsumerState<CpusSlider> {
25-
26-
22+
class _CpusSliderState extends State<CpusSlider> {
2723
final min = 1;
2824

2925
late final controller = TextEditingController(

src/client/gui/lib/vm_details/disk_slider.dart

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,27 @@
11
import 'dart:math' as math;
2-
32
import 'package:flutter/material.dart' hide Tooltip;
4-
import 'package:flutter_riverpod/flutter_riverpod.dart';
5-
6-
import '../providers.dart';
7-
import '../tooltip.dart';
83
import 'mapping_slider.dart';
4+
import '../extensions.dart';
95
import 'memory_slider.dart';
6+
import '../tooltip.dart';
107

11-
final diskSizeProvider = FutureProvider((ref) {
12-
return ref
13-
.watch(grpcClientProvider)
14-
.daemonInfo()
15-
.then((r) => r.availableSpace.toInt());
16-
});
17-
18-
class DiskSlider extends ConsumerWidget {
8+
class DiskSlider extends StatelessWidget {
199
final int? initialValue;
2010
final int min;
2111
final FormFieldSetter<int> onSaved;
22-
2312
final int maxDisk;
2413

25-
DiskSlider({
14+
const DiskSlider({
2615
super.key,
2716
int? min,
2817
this.initialValue,
2918
required this.onSaved,
30-
this.maxDisk=1,
19+
this.maxDisk = 1,
3120
}) : min = min ?? 1.gibi;
3221

3322
@override
34-
Widget build(BuildContext context, WidgetRef ref) {
35-
final disk = maxDisk ?? min;
23+
Widget build(BuildContext context) {
24+
final disk = maxDisk;
3625
final max = math.max(initialValue ?? 0, disk);
3726
final enabled = min != max;
3827

src/client/gui/lib/vm_details/ram_slider.dart

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
import 'dart:math' as math;
22

33
import 'package:flutter/material.dart';
4-
import 'package:flutter_riverpod/flutter_riverpod.dart';
54

65
import 'mapping_slider.dart';
6+
import '../extensions.dart';
77
import 'memory_slider.dart';
88

9-
class RamSlider extends ConsumerWidget {
10-
11-
9+
class RamSlider extends StatelessWidget {
1210
final int? initialValue;
1311
final FormFieldSetter<int> onSaved;
14-
1512
final int maxRam;
1613

1714
const RamSlider({
1815
super.key,
1916
this.initialValue,
2017
required this.onSaved,
21-
this.maxRam=1,
18+
this.maxRam = 1,
2219
});
2320

2421
@override
25-
Widget build(BuildContext context, WidgetRef ref) {
26-
27-
final ram = maxRam ?? 512.mebi;
22+
Widget build(BuildContext context) {
23+
final ram = maxRam;
2824

2925
return MemorySlider(
3026
label: 'Memory',

src/client/gui/lib/vm_details/vm_details_resources.dart

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class _ResourcesDetailsState extends ConsumerState<ResourcesDetails> {
4545
final stopped = ref.watch(vmInfoProvider(widget.name).select((info) {
4646
return info.instanceStatus.status == Status.STOPPED;
4747
}));
48+
final daemonInfo = ref.watch(daemonInfoProvider);
4849

4950
if (!stopped) editing = false;
5051

@@ -53,45 +54,66 @@ class _ResourcesDetailsState extends ConsumerState<ResourcesDetails> {
5354
'CPUs ${cpus?.toString() ?? '…'}',
5455
style: TextStyle(fontSize: 16),
5556
)
56-
: CpusSlider(
57-
key: Key('cpus-$cpus'),
58-
initialValue: cpus,
59-
onSaved: (value) {
60-
if (value == null || value == cpus) return;
61-
ref.read(cpusProvider.notifier).set('$value').onError(
62-
ref.notifyError((error) => 'Failed to set CPUs : $error'));
63-
},
57+
: daemonInfo.when(
58+
data: (info) => CpusSlider(
59+
key: Key('cpus-$cpus'),
60+
initialValue: cpus,
61+
maxCpus: info.cpus.toInt(),
62+
onSaved: (value) {
63+
if (value == null || value == cpus) return;
64+
ref
65+
.read(cpusProvider.notifier)
66+
.set('$value')
67+
.onError(ref.notifyError((error) => 'Failed to set CPUs : $error'));
68+
},
69+
),
70+
loading: () => CircularProgressIndicator(),
71+
error: (error, stack) => Text('Error: $error'),
6472
);
6573

6674
final ramResource = !editing
6775
? Text(
6876
'Memory ${ram.map(humanReadableMemory) ?? '…'}',
6977
style: TextStyle(fontSize: 16),
7078
)
71-
: RamSlider(
72-
key: Key('ram-$ram'),
73-
initialValue: ram,
74-
onSaved: (value) {
75-
if (value == null || value == ram) return;
76-
ref.read(ramProvider.notifier).set('${value}B').onError(
77-
ref.notifyError((e) => 'Failed to set memory size: $e'));
78-
},
79+
: daemonInfo.when(
80+
data: (info) => RamSlider(
81+
key: Key('ram-$ram'),
82+
initialValue: ram,
83+
maxRam: info.memory.toInt(),
84+
onSaved: (value) {
85+
if (value == null || value == ram) return;
86+
ref
87+
.read(ramProvider.notifier)
88+
.set('${value}B')
89+
.onError(ref.notifyError((e) => 'Failed to set memory size: $e'));
90+
},
91+
),
92+
loading: () => CircularProgressIndicator(),
93+
error: (error, stack) => Text('Error: $error'),
7994
);
8095

8196
final diskResource = !editing
8297
? Text(
8398
'Disk ${disk.map(humanReadableMemory) ?? '…'}',
8499
style: TextStyle(fontSize: 16),
85100
)
86-
: DiskSlider(
87-
key: Key('disk-$disk'),
88-
min: disk,
89-
initialValue: disk,
90-
onSaved: (value) {
91-
if (value == null || value == disk) return;
92-
ref.read(diskProvider.notifier).set('${value}B').onError(
93-
ref.notifyError((e) => 'Failed to set disk size: $e'));
94-
},
101+
: daemonInfo.when(
102+
data: (info) => DiskSlider(
103+
key: Key('disk-$disk'),
104+
min: disk,
105+
initialValue: disk,
106+
maxDisk: info.availableSpace.toInt(),
107+
onSaved: (value) {
108+
if (value == null || value == disk) return;
109+
ref
110+
.read(diskProvider.notifier)
111+
.set('${value}B')
112+
.onError(ref.notifyError((e) => 'Failed to set disk size: $e'));
113+
},
114+
),
115+
loading: () => CircularProgressIndicator(),
116+
error: (error, stack) => Text('Error: $error'),
95117
);
96118

97119
final saveButton = TextButton(

src/client/gui/pubspec.lock

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,6 @@ packages:
268268
url: "https://pub.dev"
269269
source: hosted
270270
version: "1.1.0"
271-
globbing:
272-
dependency: transitive
273-
description:
274-
name: globbing
275-
sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d"
276-
url: "https://pub.dev"
277-
source: hosted
278-
version: "1.0.0"
279271
google_identity_services_web:
280272
dependency: transitive
281273
description:
@@ -698,15 +690,6 @@ packages:
698690
url: "https://pub.dev"
699691
source: hosted
700692
version: "3.3.0+3"
701-
system_info2:
702-
dependency: "direct main"
703-
description:
704-
path: "."
705-
ref: "4.0.0+mp"
706-
resolved-ref: ea5fac0e3a03db72276d946f6ca9abc9939e737a
707-
url: "https://github.com/andrei-toterman/system_info.git"
708-
source: git
709-
version: "4.0.0"
710693
term_glyph:
711694
dependency: transitive
712695
description:

src/client/gui/pubspec.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ dependencies:
3333
rxdart: ^0.28.0
3434
shared_preferences: ^2.3.2
3535
synchronized: ^3.3.0+3
36-
system_info2:
37-
git:
38-
url: https://github.com/andrei-toterman/system_info.git
39-
ref: 4.0.0+mp
4036
tray_menu:
4137
git:
4238
url: https://github.com/andrei-toterman/tray_menu.git

src/daemon/daemon.cpp

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,11 +2789,8 @@ try // clang-format on
27892789
QStorageInfo storage_info{config->data_directory};
27902790
response.set_available_space(storage_info.bytesTotal());
27912791

2792-
#if defined(__linux__)
2793-
auto sys_info = read_linux_system_info();
2794-
response.set_cpus(sys_info.cpus);
2795-
response.set_memory(sys_info.memory);
2796-
#endif
2792+
response.set_cpus(MP_PLATFORM.get_cpus());
2793+
response.set_memory(MP_PLATFORM.get_total_ram());
27972794

27982795
server->Write(response);
27992796
status_promise->set_value(grpc::Status{});
@@ -3801,35 +3798,3 @@ void mp::Daemon::add_bridged_interface(const std::string& instance_name)
38013798
throw mp::BridgeFailureException("Cannot update instance settings", instance_name, preferred_net);
38023799
}
38033800
}
3804-
3805-
mp::LinuxSystemInfo mp::read_linux_system_info()
3806-
{
3807-
LinuxSystemInfo info{};
3808-
#if defined(__linux__)
3809-
// Simple parsing from /proc files:
3810-
{
3811-
std::ifstream cpuinfo{"/proc/cpuinfo"};
3812-
std::string line;
3813-
while (std::getline(cpuinfo, line))
3814-
{
3815-
if (line.rfind("processor", 0) == 0)
3816-
info.cpus++;
3817-
}
3818-
}
3819-
{
3820-
std::ifstream meminfo{"/proc/meminfo"};
3821-
std::string line;
3822-
while (std::getline(meminfo, line))
3823-
{
3824-
if (line.rfind("MemTotal:", 0) == 0)
3825-
{
3826-
long kb = 0;
3827-
std::sscanf(line.c_str(), "MemTotal: %ld kB", &kb);
3828-
info.memory = kb * 1024LL;
3829-
break;
3830-
}
3831-
}
3832-
}
3833-
#endif
3834-
return info;
3835-
}

0 commit comments

Comments
 (0)