summaryrefslogtreecommitdiff
path: root/src/installer-media.vala
blob: b65448c5d89ecb46ce890f97451ae4d719865450 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// This file is part of GNOME Boxes. License: LGPLv2+

using Osinfo;
using GUdev;
using GVirConfig;

private class Boxes.InstallerMedia : GLib.Object {
    public Os? os;
    public Osinfo.Resources? resources;
    public Media? os_media;
    public string label;
    public string device_file;
    public string mount_point;
    public bool from_image;

    public bool live { get { return os_media == null || os_media.live; } }

    public InstallerMedia.from_iso_info (string           path,
                                         string           label,
                                         Os               os,
                                         Media            media,
                                         Osinfo.Resources resources) {
        this.device_file = path;
        this.os = os;
        this.os_media = media;
        this.resources = resources;
        from_image = true;

        setup_label (label);
    }

    public static async InstallerMedia create_for_path (string       path,
                                                        MediaManager media_manager,
                                                        Cancellable? cancellable) throws GLib.Error {
        var media = new InstallerMedia ();

        yield media.setup_for_path (path, media_manager, cancellable);

        return media;
    }

    private async void setup_for_path (string       path,
                                       MediaManager media_manager,
                                       Cancellable? cancellable) throws GLib.Error {
        var device = yield get_device_from_path (path, media_manager.client, cancellable);

        if (device != null)
            get_media_info_from_device (device, media_manager.os_db);
        else {
            from_image = true;
            os = yield media_manager.os_db.guess_os_from_install_media (device_file, out os_media, cancellable);
        }

        setup_label ();

        // FIXME: these values could be made editable somehow
        var architecture = (os_media != null) ? os_media.architecture : "i686";
        resources = media_manager.os_db.get_resources_for_os (os, architecture);
    }

    public virtual void set_direct_boot_params (DomainOs os) {}
    public virtual async void prepare_for_installation (string vm_name, Cancellable? cancellable) throws GLib.Error {}

    public bool is_architecture_compatible (string architecture) {
        return os_media == null || // Unknown media
               os_media.architecture == architecture ||
               (os_media.architecture == "i386" && architecture == "i686") ||
               (os_media.architecture == "i386" && architecture == "x86_64") ||
               (os_media.architecture == "i686" && architecture == "x86_64");
    }

    private async GUdev.Device? get_device_from_path (string path, Client client, Cancellable? cancellable) {
        try {
            var mount_dir = File.new_for_commandline_arg (path);
            var mount = yield mount_dir.find_enclosing_mount_async (Priority.DEFAULT, cancellable);
            var root_dir = mount.get_root ();
            if (root_dir.get_path () == mount_dir.get_path ()) {
                var volume = mount.get_volume ();
                device_file = volume.get_identifier (VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
                mount_point = path;
            } else
                // Assume direct path to device node/image
                device_file = path;
        } catch (GLib.Error error) {
            // Assume direct path to device node/image
            device_file = path;
        }

        return client.query_by_device_file (device_file);
    }

    private void get_media_info_from_device (GUdev.Device device, OSDatabase os_db) throws OSDatabaseError {
        if (!device.get_property_as_boolean ("OSINFO_BOOTABLE"))
            throw new OSDatabaseError.NON_BOOTABLE ("Media %s is not bootable.", device_file);

        label = device.get_property ("ID_FS_LABEL");

        var os_id = device.get_property ("OSINFO_INSTALLER") ?? device.get_property ("OSINFO_LIVE");

        if (os_id != null) {
            os = os_db.get_os_by_id (os_id);

            var media_id = device.get_property ("OSINFO_MEDIA");
            if (media_id != null)
                os_media = os_db.get_media_by_id (os, media_id);
        }
    }

    private void setup_label (string? label = null) {
        if (label != null)
            this.label = label;
        else if (os != null)
            this.label = os.get_name ();
        else {
            // No appropriate label? :( Lets just use filename then
            this.label = Path.get_basename (device_file);

            return;
        }

        if (os_media != null && os_media.live)
            // Translators: We are appending " (Live)" suffix to name of OS media to indication that it's live.
            //              http://en.wikipedia.org/wiki/Live_CD
            this.label = _("%s (Live)").printf (this.label);
    }
}