~anso/nova/factorycleanup

« back to all changes in this revision

Viewing changes to nova/virt/libvirt_conn.py

  • Committer: Todd Willey
  • Date: 2011-01-17 18:51:00 UTC
  • mfrom: (524.1.12 wsgirouter)
  • Revision ID: todd@ansolabs.com-20110117185100-d38jerwbg8wzeg4k
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
58
58
from nova import utils
59
59
#from nova.api import context
60
60
from nova.auth import manager
61
 
from nova.compute import disk
62
61
from nova.compute import instance_types
63
62
from nova.compute import power_state
 
63
from nova.virt import disk
64
64
from nova.virt import images
65
65
 
66
66
libvirt = None
91
91
flags.DEFINE_bool('allow_project_net_traffic',
92
92
                  True,
93
93
                  'Whether to allow in project network traffic')
 
94
flags.DEFINE_bool('use_cow_images',
 
95
                  True,
 
96
                  'Whether to use cow images')
94
97
flags.DEFINE_string('ajaxterm_portrange',
95
98
                    '10000-12000',
96
99
                    'Range of ports that ajaxterm should randomly try to bind')
127
130
    return str(net.net()), str(net.netmask())
128
131
 
129
132
 
 
133
def _get_net_and_prefixlen(cidr):
 
134
    net = IPy.IP(cidr)
 
135
    return str(net.net()), str(net.prefixlen())
 
136
 
 
137
 
 
138
def _get_ip_version(cidr):
 
139
        net = IPy.IP(cidr)
 
140
        return int(net.version())
 
141
 
 
142
 
130
143
class LibvirtConnection(object):
131
144
 
132
145
    def __init__(self, read_only):
372
385
                              instance['id'],
373
386
                              power_state.NOSTATE,
374
387
                              'launching')
375
 
 
376
388
        self.nwfilter.setup_basic_filtering(instance)
377
389
        self.firewall_driver.prepare_instance_filter(instance)
378
390
        self._create_image(instance, xml)
480
492
        subprocess.Popen(cmd, shell=True)
481
493
        return {'token': token, 'host': host, 'port': port}
482
494
 
 
495
    def _cache_image(self, fn, target, fname, cow=False, *args, **kwargs):
 
496
        """Wrapper for a method that creates an image that caches the image.
 
497
 
 
498
        This wrapper will save the image into a common store and create a
 
499
        copy for use by the hypervisor.
 
500
 
 
501
        The underlying method should specify a kwarg of target representing
 
502
        where the image will be saved.
 
503
 
 
504
        fname is used as the filename of the base image.  The filename needs
 
505
        to be unique to a given image.
 
506
 
 
507
        If cow is True, it will make a CoW image instead of a copy.
 
508
        """
 
509
        if not os.path.exists(target):
 
510
            base_dir = os.path.join(FLAGS.instances_path, '_base')
 
511
            if not os.path.exists(base_dir):
 
512
                os.mkdir(base_dir)
 
513
                os.chmod(base_dir, 0777)
 
514
            base = os.path.join(base_dir, fname)
 
515
            if not os.path.exists(base):
 
516
                fn(target=base, *args, **kwargs)
 
517
            if cow:
 
518
                utils.execute('qemu-img create -f qcow2 -o '
 
519
                              'cluster_size=2M,backing_file=%s %s'
 
520
                              % (base, target))
 
521
            else:
 
522
                utils.execute('cp %s %s' % (base, target))
 
523
 
 
524
    def _fetch_image(self, target, image_id, user, project, size=None):
 
525
        """Grab image and optionally attempt to resize it"""
 
526
        images.fetch(image_id, target, user, project)
 
527
        if size:
 
528
            disk.extend(target, size)
 
529
 
 
530
    def _create_local(self, target, local_gb):
 
531
        """Create a blank image of specified size"""
 
532
        utils.execute('truncate %s -s %dG' % (target, local_gb))
 
533
        # TODO(vish): should we format disk by default?
 
534
 
483
535
    def _create_image(self, inst, libvirt_xml, prefix='', disk_images=None):
484
536
        # syntactic nicety
485
 
        basepath = lambda fname = '', prefix = prefix: os.path.join(
486
 
                                                 FLAGS.instances_path,
487
 
                                                 inst['name'],
488
 
                                                 prefix + fname)
 
537
        def basepath(fname='', prefix=prefix):
 
538
            return os.path.join(FLAGS.instances_path,
 
539
                                inst['name'],
 
540
                                prefix + fname)
489
541
 
490
542
        # ensure directories exist and are writable
491
543
        utils.execute('mkdir -p %s' % basepath(prefix=''))
492
544
        utils.execute('chmod 0777 %s' % basepath(prefix=''))
493
545
 
494
 
        # TODO(termie): these are blocking calls, it would be great
495
 
        #               if they weren't.
496
546
        LOG.info(_('instance %s: Creating image'), inst['name'])
497
547
        f = open(basepath('libvirt.xml'), 'w')
498
548
        f.write(libvirt_xml)
509
559
            disk_images = {'image_id': inst['image_id'],
510
560
                           'kernel_id': inst['kernel_id'],
511
561
                           'ramdisk_id': inst['ramdisk_id']}
512
 
        if not os.path.exists(basepath('disk')):
513
 
            images.fetch(inst.image_id, basepath('disk-raw'), user,
514
 
                         project)
515
 
 
516
 
        if inst['kernel_id']:
517
 
            if not os.path.exists(basepath('kernel')):
518
 
                images.fetch(inst['kernel_id'], basepath('kernel'),
519
 
                             user, project)
520
 
            if inst['ramdisk_id']:
521
 
                if not os.path.exists(basepath('ramdisk')):
522
 
                    images.fetch(inst['ramdisk_id'], basepath('ramdisk'),
523
 
                                 user, project)
524
 
 
525
 
        def execute(cmd, process_input=None, check_exit_code=True):
526
 
            return utils.execute(cmd=cmd,
527
 
                                 process_input=process_input,
528
 
                                 check_exit_code=check_exit_code)
 
562
 
 
563
        if disk_images['kernel_id']:
 
564
            self._cache_image(fn=self._fetch_image,
 
565
                              target=basepath('kernel'),
 
566
                              fname=disk_images['kernel_id'],
 
567
                              image_id=disk_images['kernel_id'],
 
568
                              user=user,
 
569
                              project=project)
 
570
            if disk_images['ramdisk_id']:
 
571
                self._cache_image(fn=self._fetch_image,
 
572
                                  target=basepath('ramdisk'),
 
573
                                  fname=disk_images['ramdisk_id'],
 
574
                                  image_id=disk_images['ramdisk_id'],
 
575
                                  user=user,
 
576
                                  project=project)
 
577
 
 
578
        root_fname = disk_images['image_id']
 
579
        size = FLAGS.minimum_root_size
 
580
        if inst['instance_type'] == 'm1.tiny' or prefix == 'rescue-':
 
581
            size = None
 
582
            root_fname += "_sm"
 
583
 
 
584
        self._cache_image(fn=self._fetch_image,
 
585
                          target=basepath('disk'),
 
586
                          fname=root_fname,
 
587
                          cow=FLAGS.use_cow_images,
 
588
                          image_id=disk_images['image_id'],
 
589
                          user=user,
 
590
                          project=project,
 
591
                          size=size)
 
592
        type_data = instance_types.INSTANCE_TYPES[inst['instance_type']]
 
593
 
 
594
        if type_data['local_gb']:
 
595
            self._cache_image(fn=self._create_local,
 
596
                              target=basepath('local'),
 
597
                              fname="local_%s" % type_data['local_gb'],
 
598
                              cow=FLAGS.use_cow_images,
 
599
                              local_gb=type_data['local_gb'])
529
600
 
530
601
        # For now, we assume that if we're not using a kernel, we're using a
531
602
        # partitioned disk image where the target partition is the first
541
612
        if network_ref['injected']:
542
613
            admin_context = context.get_admin_context()
543
614
            address = db.instance_get_fixed_address(admin_context, inst['id'])
 
615
            ra_server = network_ref['ra_server']
 
616
            if not ra_server:
 
617
                ra_server = "fd00::"
544
618
            with open(FLAGS.injected_network_template) as f:
545
619
                net = f.read() % {'address': address,
546
620
                                  'netmask': network_ref['netmask'],
547
621
                                  'gateway': network_ref['gateway'],
548
622
                                  'broadcast': network_ref['broadcast'],
549
 
                                  'dns': network_ref['dns']}
 
623
                                  'dns': network_ref['dns'],
 
624
                                  'ra_server': ra_server}
550
625
        if key or net:
551
626
            if key:
552
627
                LOG.info(_('instance %s: injecting key into image %s'),
555
630
                LOG.info(_('instance %s: injecting net into image %s'),
556
631
                             inst['name'], inst.image_id)
557
632
            try:
558
 
                disk.inject_data(basepath('disk-raw'), key, net,
 
633
                disk.inject_data(basepath('disk'), key, net,
559
634
                                 partition=target_partition,
560
 
                                 execute=execute)
 
635
                                 nbd=FLAGS.use_cow_images)
561
636
            except Exception as e:
562
637
                # This could be a windows image, or a vmdk format disk
563
638
                LOG.warn(_('instance %s: ignoring error injecting data'
564
639
                           ' into image %s (%s)'),
565
640
                         inst['name'], inst.image_id, e)
566
641
 
567
 
        if inst['kernel_id']:
568
 
            if os.path.exists(basepath('disk')):
569
 
                utils.execute('rm -f %s' % basepath('disk'))
570
 
 
571
 
        local_bytes = (instance_types.INSTANCE_TYPES[inst.instance_type]
572
 
                                                    ['local_gb']
573
 
                                                    * 1024 * 1024 * 1024)
574
 
 
575
 
        resize = True
576
 
        if inst['instance_type'] == 'm1.tiny' or prefix == 'rescue-':
577
 
            resize = False
578
 
 
579
 
        if inst['kernel_id']:
580
 
            disk.partition(basepath('disk-raw'), basepath('disk'),
581
 
                           local_bytes, resize, execute=execute)
582
 
        else:
583
 
            os.rename(basepath('disk-raw'), basepath('disk'))
584
 
            disk.extend(basepath('disk'), local_bytes, execute=execute)
585
 
 
586
642
        if FLAGS.libvirt_type == 'uml':
587
643
            utils.execute('sudo chown root %s' % basepath('disk'))
588
644
 
601
657
                                                   instance['id'])
602
658
        # Assume that the gateway also acts as the dhcp server.
603
659
        dhcp_server = network['gateway']
604
 
 
 
660
        ra_server = network['ra_server']
 
661
        if not ra_server:
 
662
            ra_server = 'fd00::'
605
663
        if FLAGS.allow_project_net_traffic:
606
 
            net, mask = _get_net_and_mask(network['cidr'])
607
 
            extra_params = ("<parameter name=\"PROJNET\" "
608
 
                            "value=\"%s\" />\n"
609
 
                            "<parameter name=\"PROJMASK\" "
610
 
                            "value=\"%s\" />\n") % (net, mask)
 
664
            if FLAGS.use_ipv6:
 
665
                net, mask = _get_net_and_mask(network['cidr'])
 
666
                net_v6, prefixlen_v6 = _get_net_and_prefixlen(
 
667
                                           network['cidr_v6'])
 
668
                extra_params = ("<parameter name=\"PROJNET\" "
 
669
                            "value=\"%s\" />\n"
 
670
                            "<parameter name=\"PROJMASK\" "
 
671
                            "value=\"%s\" />\n"
 
672
                            "<parameter name=\"PROJNETV6\" "
 
673
                            "value=\"%s\" />\n"
 
674
                            "<parameter name=\"PROJMASKV6\" "
 
675
                            "value=\"%s\" />\n") % \
 
676
                              (net, mask, net_v6, prefixlen_v6)
 
677
            else:
 
678
                net, mask = _get_net_and_mask(network['cidr'])
 
679
                extra_params = ("<parameter name=\"PROJNET\" "
 
680
                            "value=\"%s\" />\n"
 
681
                            "<parameter name=\"PROJMASK\" "
 
682
                            "value=\"%s\" />\n") % \
 
683
                              (net, mask)
611
684
        else:
612
685
            extra_params = "\n"
 
686
        if FLAGS.use_cow_images:
 
687
            driver_type = 'qcow2'
 
688
        else:
 
689
            driver_type = 'raw'
613
690
 
614
691
        xml_info = {'type': FLAGS.libvirt_type,
615
692
                    'name': instance['name'],
621
698
                    'mac_address': instance['mac_address'],
622
699
                    'ip_address': ip_address,
623
700
                    'dhcp_server': dhcp_server,
 
701
                    'ra_server': ra_server,
624
702
                    'extra_params': extra_params,
625
 
                    'rescue': rescue}
 
703
                    'rescue': rescue,
 
704
                    'local': instance_type['local_gb'],
 
705
                    'driver_type': driver_type}
626
706
        if not rescue:
627
707
            if instance['kernel_id']:
628
708
                xml_info['kernel'] = xml_info['basepath'] + "/kernel"
882
962
                    </rule>
883
963
                  </filter>'''
884
964
 
 
965
    def nova_ra_filter(self):
 
966
        return '''<filter name='nova-allow-ra-server' chain='root'>
 
967
                            <uuid>d707fa71-4fb5-4b27-9ab7-ba5ca19c8804</uuid>
 
968
                              <rule action='accept' direction='inout'
 
969
                                    priority='100'>
 
970
                                <icmpv6 srcipaddr='$RASERVER'/>
 
971
                              </rule>
 
972
                            </filter>'''
 
973
 
885
974
    def setup_basic_filtering(self, instance):
886
975
        """Set up basic filtering (MAC, IP, and ARP spoofing protection)"""
887
976
        logging.info('called setup_basic_filtering in nwfilter')
910
999
        self._define_filter(self.nova_base_ipv4_filter)
911
1000
        self._define_filter(self.nova_base_ipv6_filter)
912
1001
        self._define_filter(self.nova_dhcp_filter)
 
1002
        self._define_filter(self.nova_ra_filter)
913
1003
        self._define_filter(self.nova_vpn_filter)
914
1004
        if FLAGS.allow_project_net_traffic:
915
1005
            self._define_filter(self.nova_project_filter)
 
1006
            if FLAGS.use_ipv6:
 
1007
                self._define_filter(self.nova_project_filter_v6)
916
1008
 
917
1009
        self.static_filters_configured = True
918
1010
 
944
1036
 
945
1037
    def nova_base_ipv6_filter(self):
946
1038
        retval = "<filter name='nova-base-ipv6' chain='ipv6'>"
947
 
        for protocol in ['tcp', 'udp', 'icmp']:
 
1039
        for protocol in ['tcp-ipv6', 'udp-ipv6', 'icmpv6']:
948
1040
            for direction, action, priority in [('out', 'accept', 399),
949
1041
                                                ('in', 'drop', 400)]:
950
1042
                retval += """<rule action='%s' direction='%s' priority='%d'>
951
 
                               <%s-ipv6 />
 
1043
                               <%s />
952
1044
                             </rule>""" % (action, direction,
953
 
                                             priority, protocol)
 
1045
                                              priority, protocol)
954
1046
        retval += '</filter>'
955
1047
        return retval
956
1048
 
963
1055
        retval += '</filter>'
964
1056
        return retval
965
1057
 
 
1058
    def nova_project_filter_v6(self):
 
1059
        retval = "<filter name='nova-project-v6' chain='ipv6'>"
 
1060
        for protocol in ['tcp-ipv6', 'udp-ipv6', 'icmpv6']:
 
1061
            retval += """<rule action='accept' direction='inout'
 
1062
                                                   priority='200'>
 
1063
                           <%s srcipaddr='$PROJNETV6'
 
1064
                               srcipmask='$PROJMASKV6' />
 
1065
                         </rule>""" % (protocol)
 
1066
        retval += '</filter>'
 
1067
        return retval
 
1068
 
966
1069
    def _define_filter(self, xml):
967
1070
        if callable(xml):
968
1071
            xml = xml()
969
 
 
970
1072
        # execute in a native thread and block current greenthread until done
971
1073
        tpool.execute(self._conn.nwfilterDefineXML, xml)
972
1074
 
980
1082
        it makes sure the filters for the security groups as well as
981
1083
        the base filter are all in place.
982
1084
        """
983
 
 
984
1085
        if instance['image_id'] == FLAGS.vpn_image_id:
985
1086
            base_filter = 'nova-vpn'
986
1087
        else:
992
1093
        instance_secgroup_filter_children = ['nova-base-ipv4',
993
1094
                                             'nova-base-ipv6',
994
1095
                                             'nova-allow-dhcp-server']
 
1096
        if FLAGS.use_ipv6:
 
1097
            instance_secgroup_filter_children += ['nova-allow-ra-server']
995
1098
 
996
1099
        ctxt = context.get_admin_context()
997
1100
 
998
1101
        if FLAGS.allow_project_net_traffic:
999
1102
            instance_filter_children += ['nova-project']
 
1103
            if FLAGS.use_ipv6:
 
1104
                instance_filter_children += ['nova-project-v6']
1000
1105
 
1001
1106
        for security_group in db.security_group_get_by_instance(ctxt,
1002
1107
                                                               instance['id']):
1024
1129
        security_group = db.security_group_get(context.get_admin_context(),
1025
1130
                                               security_group_id)
1026
1131
        rule_xml = ""
 
1132
        v6protocol = {'tcp': 'tcp-ipv6', 'udp': 'udp-ipv6', 'icmp': 'icmpv6'}
1027
1133
        for rule in security_group.rules:
1028
1134
            rule_xml += "<rule action='accept' direction='in' priority='300'>"
1029
1135
            if rule.cidr:
1030
 
                net, mask = _get_net_and_mask(rule.cidr)
1031
 
                rule_xml += "<%s srcipaddr='%s' srcipmask='%s' " % \
1032
 
                            (rule.protocol, net, mask)
 
1136
                version = _get_ip_version(rule.cidr)
 
1137
                if(FLAGS.use_ipv6 and version == 6):
 
1138
                    net, prefixlen = _get_net_and_prefixlen(rule.cidr)
 
1139
                    rule_xml += "<%s srcipaddr='%s' srcipmask='%s' " % \
 
1140
                                (v6protocol[rule.protocol], net, prefixlen)
 
1141
                else:
 
1142
                    net, mask = _get_net_and_mask(rule.cidr)
 
1143
                    rule_xml += "<%s srcipaddr='%s' srcipmask='%s' " % \
 
1144
                                (rule.protocol, net, mask)
1033
1145
                if rule.protocol in ['tcp', 'udp']:
1034
1146
                    rule_xml += "dstportstart='%s' dstportend='%s' " % \
1035
1147
                                (rule.from_port, rule.to_port)
1044
1156
 
1045
1157
                rule_xml += '/>\n'
1046
1158
            rule_xml += "</rule>\n"
1047
 
        xml = "<filter name='nova-secgroup-%s' chain='ipv4'>%s</filter>" % \
1048
 
              (security_group_id, rule_xml,)
 
1159
        xml = "<filter name='nova-secgroup-%s' " % security_group_id
 
1160
        if(FLAGS.use_ipv6):
 
1161
            xml += "chain='root'>%s</filter>" % rule_xml
 
1162
        else:
 
1163
            xml += "chain='ipv4'>%s</filter>" % rule_xml
1049
1164
        return xml
1050
1165
 
1051
1166
    def _instance_filter_name(self, instance):
1082
1197
    def apply_ruleset(self):
1083
1198
        current_filter, _ = self.execute('sudo iptables-save -t filter')
1084
1199
        current_lines = current_filter.split('\n')
1085
 
        new_filter = self.modify_rules(current_lines)
 
1200
        new_filter = self.modify_rules(current_lines, 4)
1086
1201
        self.execute('sudo iptables-restore',
1087
1202
                     process_input='\n'.join(new_filter))
 
1203
        if(FLAGS.use_ipv6):
 
1204
            current_filter, _ = self.execute('sudo ip6tables-save -t filter')
 
1205
            current_lines = current_filter.split('\n')
 
1206
            new_filter = self.modify_rules(current_lines, 6)
 
1207
            self.execute('sudo ip6tables-restore',
 
1208
                         process_input='\n'.join(new_filter))
1088
1209
 
1089
 
    def modify_rules(self, current_lines):
 
1210
    def modify_rules(self, current_lines, ip_version=4):
1090
1211
        ctxt = context.get_admin_context()
1091
1212
        # Remove any trace of nova rules.
1092
1213
        new_filter = filter(lambda l: 'nova-' not in l, current_lines)
1100
1221
                if not new_filter[rules_index].startswith(':'):
1101
1222
                    break
1102
1223
 
1103
 
        our_chains = [':nova-ipv4-fallback - [0:0]']
1104
 
        our_rules = ['-A nova-ipv4-fallback -j DROP']
 
1224
        our_chains = [':nova-fallback - [0:0]']
 
1225
        our_rules = ['-A nova-fallback -j DROP']
1105
1226
 
1106
1227
        our_chains += [':nova-local - [0:0]']
1107
1228
        our_rules += ['-A FORWARD -j nova-local']
1112
1233
        for instance_id in self.instances:
1113
1234
            instance = self.instances[instance_id]
1114
1235
            chain_name = self._instance_chain_name(instance)
1115
 
            ip_address = self._ip_for_instance(instance)
 
1236
            if(ip_version == 4):
 
1237
                ip_address = self._ip_for_instance(instance)
 
1238
            elif(ip_version == 6):
 
1239
                ip_address = self._ip_for_instance_v6(instance)
1116
1240
 
1117
1241
            our_chains += [':%s - [0:0]' % chain_name]
1118
1242
 
1139
1263
 
1140
1264
                our_rules += ['-A %s -j %s' % (chain_name, sg_chain_name)]
1141
1265
 
1142
 
            # Allow DHCP responses
1143
 
            dhcp_server = self._dhcp_server_for_instance(instance)
1144
 
            our_rules += ['-A %s -s %s -p udp --sport 67 --dport 68' %
1145
 
                                                     (chain_name, dhcp_server)]
 
1266
            if(ip_version == 4):
 
1267
                # Allow DHCP responses
 
1268
                dhcp_server = self._dhcp_server_for_instance(instance)
 
1269
                our_rules += ['-A %s -s %s -p udp --sport 67 --dport 68' %
 
1270
                                                 (chain_name, dhcp_server)]
 
1271
            elif(ip_version == 6):
 
1272
                # Allow RA responses
 
1273
                ra_server = self._ra_server_for_instance(instance)
 
1274
                our_rules += ['-A %s -s %s -p icmpv6' %
 
1275
                                                 (chain_name, ra_server)]
1146
1276
 
1147
1277
            # If nothing matches, jump to the fallback chain
1148
 
            our_rules += ['-A %s -j nova-ipv4-fallback' % (chain_name,)]
 
1278
            our_rules += ['-A %s -j nova-fallback' % (chain_name,)]
1149
1279
 
1150
1280
        # then, security group chains and rules
1151
1281
        for security_group_id in security_groups:
1158
1288
 
1159
1289
            for rule in rules:
1160
1290
                logging.info('%r', rule)
1161
 
                args = ['-A', chain_name, '-p', rule.protocol]
1162
1291
 
1163
 
                if rule.cidr:
1164
 
                    args += ['-s', rule.cidr]
1165
 
                else:
 
1292
                if not rule.cidr:
1166
1293
                    # Eventually, a mechanism to grant access for security
1167
1294
                    # groups will turn up here. It'll use ipsets.
1168
1295
                    continue
1169
1296
 
 
1297
                version = _get_ip_version(rule.cidr)
 
1298
                if version != ip_version:
 
1299
                    continue
 
1300
 
 
1301
                protocol = rule.protocol
 
1302
                if version == 6 and rule.protocol == 'icmp':
 
1303
                    protocol = 'icmpv6'
 
1304
 
 
1305
                args = ['-A', chain_name, '-p', protocol, '-s', rule.cidr]
 
1306
 
1170
1307
                if rule.protocol in ['udp', 'tcp']:
1171
1308
                    if rule.from_port == rule.to_port:
1172
1309
                        args += ['--dport', '%s' % (rule.from_port,)]
1186
1323
                            icmp_type_arg += '/%s' % icmp_code
1187
1324
 
1188
1325
                    if icmp_type_arg:
1189
 
                        args += ['-m', 'icmp', '--icmp-type', icmp_type_arg]
 
1326
                        if(ip_version == 4):
 
1327
                            args += ['-m', 'icmp', '--icmp-type',
 
1328
                                     icmp_type_arg]
 
1329
                        elif(ip_version == 6):
 
1330
                            args += ['-m', 'icmp6', '--icmpv6-type',
 
1331
                                     icmp_type_arg]
1190
1332
 
1191
1333
                args += ['-j ACCEPT']
1192
1334
                our_rules += [' '.join(args)]
1212
1354
        return db.instance_get_fixed_address(context.get_admin_context(),
1213
1355
                                             instance['id'])
1214
1356
 
 
1357
    def _ip_for_instance_v6(self, instance):
 
1358
        return db.instance_get_fixed_address_v6(context.get_admin_context(),
 
1359
                                             instance['id'])
 
1360
 
1215
1361
    def _dhcp_server_for_instance(self, instance):
1216
1362
        network = db.project_get_network(context.get_admin_context(),
1217
1363
                                         instance['project_id'])
1218
1364
        return network['gateway']
 
1365
 
 
1366
    def _ra_server_for_instance(self, instance):
 
1367
        network = db.project_get_network(context.get_admin_context(),
 
1368
                                         instance['project_id'])
 
1369
        return network['ra_server']