• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

xapi-project / xen-api / 13457957190

21 Feb 2025 01:35PM CUT coverage: 78.516%. Remained the same
13457957190

Pull #6312

github

Vincent-lau
CA-407033: Call `receive_finalize2` synchronously

`Remote.receive_finalize2` is called at the end of SXM to clean things
up and compose the base and leaf images together. The compose operation
should only be called while the VDI is deactivated. Currently a thread
is created to call `receive_finalize2`, which could caused problems
where the VM itself gets started while the `receive_finalize2`/`VDI.compose`
is still in progress. This is not a safe operation to do.

The fix here is to simply remove the thread and make the whole operation
sequential.

Signed-off-by: Vincent Liu <shuntian.liu2@cloud.com>
Pull Request #6312: CA-407033: Call `receive_finalize2` synchronously

3512 of 4473 relevant lines covered (78.52%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

33.55
/ocaml/xenopsd/scripts/common.py
1
#!/usr/bin/python3
2
#
3
# Copyright (c) 2011-2013 Citrix Systems, Inc.
4
#
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU Lesser General Public License as published
7
# by the Free Software Foundation; version 2.1 only. with the special
8
# exception on linking described in file LICENSE.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU Lesser General Public License for more details.
14
#
15
import os
1✔
16
import os.path
1✔
17
import sys
1✔
18
import syslog
1✔
19
import subprocess
1✔
20

21
path = "/sbin:/usr/sbin:/bin:/usr/bin:" + os.path.dirname(sys.argv[0])
1✔
22
vif_hotplug = "/etc/xapi.d/vif-hotplug"
1✔
23
xs_read = "/usr/bin/xenstore-read"
1✔
24
xenops_base_path = "/var/run/nonpersistent/xenopsd"
1✔
25
xenops_path = None
1✔
26

27
command_name = sys.argv[0]
1✔
28
short_command_name = os.path.basename(command_name)
1✔
29

30
def set_xenopsd_backend(b):
1✔
31
    global xenops_path
32
    xenops_path = os.path.join(xenops_base_path, b)
×
33

34
def send_to_syslog(msg):
1✔
35
    pid = os.getpid()
×
36
    syslog.syslog("%s[%d] - %s" %(command_name, pid, msg))
×
37

38
def doexec(args):
1✔
39
    """Execute a subprocess, then return its return code, stdout and stderr"""
40
    send_to_syslog(args)
×
41
    proc = subprocess.Popen([ "/usr/bin/env", "PATH=%s" % path ] + args, stdin=None, stdout=subprocess.PIPE,
×
42
                            stderr=subprocess.PIPE, close_fds=True, universal_newlines=True)
43
    rc = proc.wait()
×
44
    stdout = proc.stdout
×
45
    stderr = proc.stderr
×
46
    return (rc, stdout, stderr)
×
47

48
ON_ERROR_LOG  = 1
1✔
49
ON_ERROR_FAIL = 2
1✔
50

51
def run(on_error, args):
1✔
52
    """Execute a subprocess and, on failure, either log (ON_ERROR_LOG) or throw (ON_ERROR_FAIL)"""
53
    (rc, stdout, stderr) = doexec(args)
×
54
    if rc != 0:
×
55
        if on_error == ON_ERROR_FAIL:
×
56
             send_to_syslog("FATAL: %s exitted with %d: %s" % (" ".join(args), rc, stderr))
×
57
             sys.exit(1)
×
58
        send_to_syslog("%s exitted with %d: %s" % (" ".join(args), rc, stderr))
×
59
        if on_error != ON_ERROR_LOG:
×
60
             send_to_syslog("... and an unrecognised on_error code was used (%d)" % on_error)
×
61

62
MODE_OPENVSWITCH = "openvswitch"
1✔
63
MODE_BRIDGE      = "bridge"
1✔
64

65
def set_promiscuous(mode, dev, value):
1✔
66
    if mode == MODE_OPENVSWITCH and value:
×
67
        send_to_syslog("%s: Promiscuous ports are not supported via Open vSwitch")
×
68
    elif mode == MODE_BRIDGE:
×
69
        promisc = "/sys/class/net/%s/brport/promisc" % dev
×
70
        if os.path.exists(promisc):
×
71
            f = open("/sys/class/net/%s/brport/promisc" % dev)
×
72
            try:
×
73
                x = "0"
×
74
                if value:
×
75
                    x = "1"
×
76
                f.write(x)
×
77
            finally:
78
                f.close()
×
79
        else:
80
            send_to_syslog("cannot set promiscuous mode: %s doesn't exist" % promisc)
×
81

82
def set_ethtool(mode, dev, key, value):
1✔
83
    x = "off"
×
84
    if value:
×
85
        x = "on"
×
86
    run(ON_ERROR_LOG, ["ethtool", "-K", dev, key, x])
×
87

88
def set_mtu(mode, dev, mtu):
1✔
89
    send_to_syslog("Setting %s MTU %d" % (dev, mtu))
×
90
    run(ON_ERROR_LOG, ["ip", "link", "set", dev, "mtu", "%d" % mtu])
×
91

92
def add_to_bridge(mode, dev, bridge, address, external_ids):
1✔
93
    send_to_syslog("Adding %s to %s with address %s" % (dev, bridge, address))
×
94
    for cmd in [ ["down"], ["arp", "off"], ["multicast", "off"], ["address", address] ]:
×
95
        run(ON_ERROR_LOG, ["ip", "link", "set", dev] + cmd)
×
96
    run(ON_ERROR_LOG, ["ip", "addr", "flush", dev])
×
97

98
    if mode == MODE_BRIDGE:
×
99
        run(ON_ERROR_LOG, ["brctl", "setfd", bridge, "0"])
×
100
        run(ON_ERROR_LOG, ["brctl", "addif", bridge, dev])
×
101
    elif mode == MODE_OPENVSWITCH:
×
102
        cmd = ["ovs-vsctl", "--timeout=30", "--", "--if-exists", "del-port", dev, "--", "add-port", bridge, dev]
×
103
        for (key, value) in external_ids:
×
104
             cmd = cmd + ["--", "set", "interface", dev, 'external-ids:"%s"="%s"' % (key, value) ]
×
105
        run(ON_ERROR_LOG, cmd)
×
106

107
def remove_from_bridge(mode, dev, bridge):
1✔
108
    if mode == MODE_BRIDGE:
×
109
        run(ON_ERROR_LOG, ["brctl", "delif", bridge, dev])
×
110
    elif mode == MODE_OPENVSWITCH:
×
111
        run(ON_ERROR_LOG, ["ovs-vsctl", "--timeout=30", "--", "--if-exists", "del-port", dev])
×
112

113

114
def call_hook_script(action, vif_uuid, vm_uuid):
1✔
115
    if os.path.exists(vif_hotplug):
×
116
        send_to_syslog("Calling VIF hotplug hook for VM %s, VIF %s" % (vm_uuid, vif_uuid))
×
117
        run(ON_ERROR_LOG, [vif_hotplug, "-action", action, "-vifuuid", vif_uuid, "-vmuuid", vm_uuid])
×
118

119
def add_vif_rules(name):
1✔
120
    # ideally we would convert setup-vif-rules into a shared library and call
121
    # the functions directly
122
    type = name[0:3]
×
123
    rest = name[3:]
×
124
    domid, devid = rest.split(".")
×
125
    run(ON_ERROR_FAIL, ["setup-vif-rules", type, domid, devid, "filter"])     
×
126

127
## Read xenopsd internal VIF metadata
128
try:
1✔
129
        import json
1✔
130
except ImportError:
×
131
        import simplejson as json
×
132

133
class VIF:
1✔
134
    def __init__(self, vif_name, vm_uuid, devid):
1✔
135
        self.vif_name = vif_name
×
136
        self.vm_uuid = vm_uuid
×
137
        self.devid = devid
×
138
        f = open("%s/VM/%s/vif.%d" % (xenops_path, vm_uuid, devid))
×
139
        try:
×
140
            self.json = json.loads(f.read())
×
141
        finally:
142
            f.close()
×
143
    def get_mode(self):
1✔
144
        x = MODE_BRIDGE
×
145
        if(os.path.exists("/sys/module/openvswitch")):
×
146
            x = MODE_OPENVSWITCH
×
147
        send_to_syslog("common.py: Detected network backend as: '%s'" % x)
×
148
        return x
×
149
    def get_bridge(self):
1✔
150
        network = self.json["backend"]
×
151
        if network[0] != "Local":
×
152
            send_to_syslog("VIF %s/%d: don't support network backend %s" % (self.vm_uuid, self.devid, repr(network)))
×
153
            return None
×
154
        return network[1]
×
155
    def get_address(self):
1✔
156
        return "fe:ff:ff:ff:ff:ff"
×
157

158
    def get_mac(self):
1✔
159
        return self.json["mac"]
×
160
    def get_mtu(self):
1✔
161
        return self.json["mtu"]
×
162
    def get_promiscuous(self):
1✔
163
        if "promiscuous" in self.json["other_config"]:
×
164
            x = self.json["other_config"]["promiscuous"]
×
165
            if x == "true" or x == "on":
×
166
                return True
×
167
        return False
×
168
    def get_external_ids(self):
1✔
169
        results = {}
×
170
        # if this is a migration target VM, we have to use final-uuid as value of `xs-vm-uuid`
171
        rc, stdout, _ = doexec([xs_read, '/vm/%s/final-uuid' % self.vm_uuid])
×
172
        if rc == 0:
×
173
            vm_uuid = stdout.readline().strip()
×
174
            send_to_syslog("This is a migration target VM, so fix value of 'xs-vm-uuid' from %s to %s" % (self.vm_uuid, vm_uuid))
×
175
        else:
176
            vm_uuid = self.vm_uuid
×
177
        results["xs-vm-uuid"] = vm_uuid
×
178
        if "vif-uuid" in self.json["extra_private_keys"]:
×
179
            results["xs-vif-uuid"] = self.json["extra_private_keys"]["vif-uuid"]
×
180
        if "network-uuid" in self.json["extra_private_keys"]:
×
181
            results["xs-network-uuid"] = self.json["extra_private_keys"]["network-uuid"]
×
182
        results["attached-mac"] = self.get_mac()
×
183
        return results
×
184

185
    def get_locking_mode(self):
1✔
186
        """
187
        Get the locking mode configuration for the VIF.
188

189
        :returns dict: A dictionary containing the locking mode configuration with keys:
190
        - mac: The MAC address
191
        - locking_mode: The locking mode
192
        - ipv4_allowed: List of IPv4 addresses allowed
193
        - ipv6_allowed: List of IPv6 addresses allowed
194
        """
195
        results = {
1✔
196
            "mac": self.get_mac(),
197
            "locking_mode": "",
198
            "ipv4_allowed": [],
199
            "ipv6_allowed": [],
200
        }
201
        if "locking_mode" in self.json:
1✔
202
            if isinstance(self.json["locking_mode"], list):
1✔
203
                # Must be type=locked and have keys for allowed ipv4 and ipv6 addresses
204
                results["locking_mode"] = self.json["locking_mode"][0].lower()
1✔
205
                locked_params = self.json["locking_mode"][1]
1✔
206
                results["ipv4_allowed"] = locked_params["ipv4"]
1✔
207
                results["ipv6_allowed"] = locked_params["ipv6"]
1✔
208
            else:
209
                results["locking_mode"] = self.json["locking_mode"].lower()
1✔
210
        send_to_syslog("Got locking config: " + repr(results))
1✔
211
        return results
1✔
212

213
class Interface:
1✔
214
    def __init__(self, vif_name, uuid, devid):
1✔
215
        self.uuid = uuid
×
216
        self.devid = int(devid)
×
217
        self.vif = VIF(vif_name, uuid, int(devid))
×
218
    def get_vif(self):
1✔
219
        return self.vif
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc