summaryrefslogtreecommitdiff
path: root/opendc/models/machine.py
blob: 52cf221bd056cee7b89b236a60b8e629533d1732 (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
127
128
129
import copy

from opendc.models.model import Model
from opendc.models.rack import Rack
from opendc.util import database, exceptions

class Machine(Model):

    JSON_TO_PYTHON_DICT = {
        'machine': {
            'id': 'id',
            'rackId': 'rack_id',
            'position': 'position',
            'tags': 'tags',
            'cpuIds': 'cpu_ids',
            'gpuIds': 'gpu_ids',
            'memoryIds': 'memory_ids',
            'storageIds': 'storage_ids'
        }
    }

    PATH = '/v1/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack/machines'

    TABLE_NAME = 'machines'
    COLUMNS = ['id', 'rack_id', 'position']
    COLUMNS_PRIMARY_KEY = ['id']

    device_table_to_attribute = {
        'cpus': 'cpu_ids',
        'gpus': 'gpu_ids',
        'memories': 'memory_ids',
        'storages': 'storage_ids'
    }

    def _update_devices(self, before_insert):
        """Update this Machine's devices in the database."""
        
        for device_table in self.device_table_to_attribute.keys():

            # First, create the statements to execute

            statements = []
            values = []

            # First, delete current machine-device links

            statement = 'DELETE FROM machine_{} WHERE machine_id = ?'.format(device_table)
            database.execute(statement, (before_insert.id,))

            # Then, add current ones
            
            for device_id in getattr(before_insert, before_insert.device_table_to_attribute[device_table]):

                statement = 'INSERT INTO machine_{} (machine_id, {}) VALUES (?, ?)'.format(
                    device_table,
                    before_insert.device_table_to_attribute[device_table][:-1]
                )
                
                database.execute(statement, (before_insert.id, device_id)) 

    @classmethod
    def from_tile_id_and_rack_position(cls, tile_id, position):
        """Get a Rack from the ID of the tile its Rack is on, and its position in the Rack."""

        try:
            rack = Rack.from_tile_id(tile_id)
        except:
            return cls(id = -1)
        
        try:
            statement = 'SELECT id FROM machines WHERE rack_id = ? AND position = ?'
            machine_id = database.fetchone(statement, (rack.id, position))[0]
        except:
            return cls(id = -1)

        return cls.from_primary_key((machine_id,))

    def google_id_has_at_least(self, google_id, authorization_level):
        """Return True if the user has at least the given auth level over this Machine."""

        # Get the Rack

        try:
            rack = Rack.from_primary_key((self.rack_id,))
        except exceptions.RowNotFoundError:
            return False

        # Check the Rack's Authorization

        return rack.google_id_has_at_least(google_id, authorization_level)

    def insert(self):
        """Insert this Machine by also updating its devices."""

        before_insert = copy.deepcopy(self)
        
        super(Machine, self).insert()

        before_insert.id = self.id
        self._update_devices(before_insert)

    def read(self):
        """Read this Machine by also getting its CPU, GPU, Memory and Storage IDs."""
        
        super(Machine, self).read()

        for device_table in self.device_table_to_attribute.keys():
            
            statement = 'SELECT * FROM machine_{} WHERE machine_id = ?'.format(device_table)
            results = database.fetchall(statement, (self.id,))
        
            device_ids = []

            for row in results:
                device_ids.append(row[2])

            setattr(self, self.device_table_to_attribute[device_table], device_ids)
        
        setattr(self, 'tags', [])

    def update(self):
        """Update this Machine by also updating its devices."""

        before_update = copy.deepcopy(self)

        super(Machine, self).update()

        before_update.id = self.id
        self._update_devices(before_update)